Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Открой для себя волшебный мир реальной рыбалки. Лови реальную рыбу на реальных водоемах! Исследуй новые рыболовные места и заполучи заветный трофей.

Реальная Рыбалка

Симуляторы, Мультиплеер, Спорт

Играть

Топ прошлой недели

  • AlexKud AlexKud 38 постов
  • SergeyKorsun SergeyKorsun 12 постов
  • SupportHuaport SupportHuaport 5 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня

Golang

С этим тегом используют

Программирование IT Программист Разработка Все
84 поста сначала свежее
2
PENTEST.DNA
PENTEST.DNA
1 год назад
Web-технологии

Создание TCP-прокси⁠⁠

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Вы можете реализовать все 𝗧𝗖𝗣-взаимодействия, используя встроенный в 𝗚𝗼 пакет 𝗻𝗲𝘁. В предыдущем разделе мы сосредоточились главным образом на его применении с позиции клиента. В этом же разделе задействуем его для создания 𝗧𝗖𝗣-серверов и передачи данных. Изучение этого процесса начнется с создания эхо-сервера — сервера, который просто возвращает запрос обратно клиенту. Затем мы создадим две более универсальные в применении программы: переадресатор 𝗧𝗖𝗣-портов и 𝗡𝗲𝘁𝗰𝗮𝘁-функцию «зияющая дыра в безопасности», применяемую для удаленного выполнения команд.


Использование io.Reader и io.Writer



При создании примеров этого раздела вам потребуется задействовать два значимых типа: 𝗶𝗼.𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗶𝗼.𝗪𝗿𝗶𝘁𝗲𝗿. Они необходимы для всех задач ввода/вывода (𝗜/𝗢) вне зависимости от того, задействуете вы 𝗧𝗖𝗣, 𝗛𝗧𝗧𝗣, файловую систему или любые другие средства. Будучи частью встроенного в 𝗚𝗼 пакета 𝗶𝗼, эти типы являются краеугольным камнем любой передачи данных, как локальной, так и сетевой. В документации они определены так:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Оба типа определяются как интерфейсы, то есть напрямую их создать нельзя. Каждый тип содержит определение одной экспортируемой функции: 𝗥𝗲𝗮𝗱 или 𝗪𝗿𝗶𝘁𝗲. Можно рассматривать эти функции как абстрактные методы, которые должны быть реализованы в типе, чтобы он считался 𝗥𝗲𝗮𝗱𝗲𝗿 или 𝗪𝗿𝗶𝘁𝗲𝗿. Например, следующий искусственный тип выполняет это соглашение и может использоваться там, где приемлем 𝗥𝗲𝗮𝗱𝗲𝗿:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Давайте с помощью них создадим что-нибудь полуготовое: настраиваемый 𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗪𝗿𝗶𝘁𝗲𝗿, обертывающий 𝘀𝘁𝗱𝗶𝗻 и 𝘀𝘁𝗱𝗼𝘂𝘁. Код для этого тоже будет несколько искусственным, так как типы 𝗚𝗼 𝗼𝘀.𝗦𝘁𝗱𝗶𝗻 и 𝗼𝘀.𝗦𝘁𝗱𝗼𝘂𝘁 уже действуют как 𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗪𝗿𝗶𝘁𝗲𝗿. Но если не пытаться изобрести колесо, то ничему и не научишься, ведь так?

Ниже показана полная реализация, а далее дано пояснение.

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Реализация reader и writer /io-example/main.go

Этот код определяет два пользовательских типа: 𝗙𝗼𝗼𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗙𝗼𝗼𝗪𝗿𝗶𝘁𝗲𝗿. В каждом типе вы определяете конкретную реализацию функции 𝗥𝗲𝗮𝗱([]𝗯𝘆𝘁𝗲) для 𝗙𝗼𝗼𝗥𝗲𝗮𝗱𝗲𝗿 и функции 𝗪𝗿𝗶𝘁𝗲([]𝗯𝘆𝘁𝗲) для 𝗙𝗼𝗼𝗪𝗿𝗶𝘁𝗲𝗿. В этом случае обе функции считывают из 𝘀𝘁𝗱𝗶𝗻 и записывают в 𝘀𝘁𝗱𝗼𝘂𝘁.

Обратите внимание на то, что функции 𝗥𝗲𝗮𝗱 и в 𝗙𝗼𝗼𝗥𝗲𝗮𝗱𝗲𝗿, и в 𝗼𝘀.𝗦𝘁𝗱𝗶𝗻 возвращают длину данных и все ошибки. Сами эти данные копируются в срез 𝗯𝘆𝘁𝗲, передаваемый этой функции. Это согласуется с начальным определением интерфейса 𝗥𝗲𝗮𝗱𝗲𝗿, приведенным в данном разделе ранее. Функция 𝗺𝗮𝗶𝗻() создает этот срез с названием 𝗶𝗻𝗽𝘂𝘁 и затем использует его в вызовах к 𝗙𝗼𝗼𝗥𝗲𝗮𝗱𝗲𝗿.𝗥𝗲𝗮𝗱([]𝗯𝘆𝘁𝗲) и 𝗙𝗼𝗼𝗥𝗲𝗮𝗱𝗲𝗿.𝗪𝗿𝗶𝘁𝗲([]𝗯𝘆𝘁𝗲).

При пробном запуске программы мы получим следующий вывод:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Копирование данных из 𝗥𝗲𝗮𝗱𝗲𝗿 в 𝗪𝗿𝗶𝘁𝗲𝗿 — это настолько распространенный шаблон, что пакет 𝗶𝗼 содержит специальную функцию 𝗖𝗼𝗽𝘆(), которую можно задействовать для упрощения функции 𝗺𝗮𝗶𝗻(). Вот ее прототип:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Эта удобная функция позволяет реализовывать то же поведение программы, что и ранее, заменив 𝗺𝗮𝗶𝗻() кодом, показанным ниже.

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Применение io.Copy /ch-2/copy-example/main.go

Обратите внимание, что явные вызовы 𝗿𝗲𝗮𝗱𝗲𝗿.𝗥𝗲𝗮𝗱([ ]𝗯𝘆𝘁𝗲) и 𝘄𝗿𝗶𝘁𝗲𝗿.𝗪𝗿𝗶𝘁𝗲([ ] 𝗯𝘆𝘁𝗲) были замещены одним вызовом 𝗶𝗼.𝗖𝗼𝗽𝘆(𝘄𝗿𝗶𝘁𝗲𝗿, 𝗿𝗲𝗮𝗱𝗲𝗿). Внутренне 𝗶𝗼.𝗖𝗼𝗽𝘆(𝘄𝗿𝗶𝘁𝗲𝗿, 𝗿𝗲𝗮𝗱𝗲𝗿) вызывает в переданном ридере функцию 𝗥𝗲𝗮𝗱([ ]𝗯𝘆𝘁𝗲), в результате чего 𝗙𝗼𝗼𝗥𝗲𝗮𝗱𝗲𝗿 выполняет считывание из 𝘀𝘁𝗱𝗶𝗻. Далее 𝗶𝗼.𝗖𝗼𝗽𝘆(𝘄𝗿𝗶𝘁𝗲𝗿, 𝗿𝗲𝗮𝗱𝗲𝗿) вызывает в переданном райтере функцию 𝗪𝗿𝗶𝘁𝗲([ ]𝗯𝘆𝘁𝗲), что приводит к вызову 𝗙𝗼𝗼𝗪𝗿𝗶𝘁𝗲𝗿, записывающего данные в 𝘀𝘁𝗱𝗼𝘂𝘁. По сути, 𝗶𝗼.𝗖𝗼𝗽𝘆(𝘄𝗿𝗶𝘁𝗲𝗿, 𝗿𝗲𝗮𝗱𝗲𝗿) обрабатывает последовательный процесс чтения/записи без лишних деталей.

Этот вводный раздел никак нельзя считать подробным рассмотрением системы 𝗜/𝗢 и интерфейсов в 𝗚𝗼. Многие вспомогательные функции и пользовательские ридеры/райтеры существуют как часть стандартных пакетов 𝗚𝗼. В большинстве случаев эти стандартные пакеты содержат все основные реализации, необходимые для реализации большинства распространенных задач. В следующем разделе мы рассмотрим применение всех этих основ к 𝗧𝗖𝗣-коммуникациям и в итоге применим полученные навыки для разработки реальных рабочих инструментов.



Создание эхо-сервера:

Как и во многих языках, изучение процесса чтения/записи данных с сокета мы начнем с построения эхо-сервера. Для этого будем использовать 𝗻𝗲𝘁.𝗖𝗼𝗻𝗻 — потокоориентированное соединение 𝗚𝗼, с которым вы уже познакомились при создании сканера портов. Как указано в документации для этого типа данных, 𝗖𝗼𝗻𝗻 реализует функции 𝗥𝗲𝗮𝗱([ ]𝗯𝘆𝘁𝗲) и 𝗪𝗿𝗶𝘁𝗲([ ]𝗯𝘆𝘁𝗲) согласно определению для интерфейсов 𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗪𝗿𝗶𝘁𝗲𝗿. Следовательно, 𝗖𝗼𝗻𝗻 одновременно является и 𝗥𝗲𝗮𝗱𝗲𝗿, и 𝗪𝗿𝗶𝘁𝗲𝗿 (да, такое возможно). Это вполне логично, так как 𝗧𝗖𝗣-соединения двунаправленные и могут использоваться для отправки (записи) и получения (чтения) данных.

После создания экземпляра conn вы сможете отправлять и получать данные через TCP-сокет. Тем не менее TCP-сервер не может просто создать соединение, его должен установить клиент. В 𝗚𝗼 для начального открытия 𝗧𝗖𝗣-слушателя на конкретном порте можно использовать 𝗻𝗲𝘁.𝗟𝗶𝘀𝘁𝗲𝗻(𝗻𝗲𝘁𝘄𝗼𝗿𝗸, 𝗮𝗱𝗱𝗿𝗲𝘀𝘀 𝘀𝘁𝗿𝗶𝗻𝗴). После подключения клиента метод 𝗔𝗰𝗰𝗲𝗽𝘁() создает и возвращает объект 𝗖𝗼𝗻𝗻, который вы можете применять для получения и отправки данных.

Ниже показан полноценный пример реализации сервера. Для большей ясности мы добавили в код комментарии. Не стремитесь сразу понять весь код, так как позже мы подробно его поясним.

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Базовый эхо-сервер /ch-2/echo-server/main.go

Базовый эхо-сервер начинается с определения функции 𝗲𝗰𝗵𝗼(𝗻𝗲𝘁.𝗖𝗼𝗻𝗻), которая принимает в качестве параметра экземпляр 𝗖𝗼𝗻𝗻. Он выступает в роли обработчика соединения, выполняя все необходимые операции 𝗜/𝗢. Эта функция повторяется бесконечно, используя буфер для считывания данных из соединения и их записи в него. Данные считываются в переменную 𝗯, после чего записываются обратно в соединение.

Теперь нужно настроить слушатель, который будет вызывать обработчик. Как ранее говорилось, сервер не может сам создать соединение и должен прослушивать подключение клиента. Следовательно, слушатель, определенный как 𝘁𝗰𝗽, привязанный к порту 𝟮𝟬𝟬𝟴𝟬, запускается во всех интерфейсах посредством функции 𝗻𝗲𝘁.𝗟𝗶𝘀𝘁𝗲𝗻(𝗻𝗲𝘁𝘄𝗼𝗿𝗸, 𝗮𝗱𝗱𝗿𝗲𝘀𝘀 𝘀𝘁𝗿𝗶𝗻𝗴).

Далее бесконечный цикл обеспечивает, чтобы сервер продолжал прослушивание соединений даже после того, как оно было установлено. В этом цикле происходит вызов 𝗹𝗶𝘀𝘁𝗲𝗻𝗲𝗿.𝗔𝗰𝗰𝗲𝗽𝘁() ❻ — функции, блокирующей выполнение при ожидании подключений. Когда клиент подключается, эта функция возвращает экземпляр 𝗖𝗼𝗻𝗻. Напомним, что 𝗖𝗼𝗻𝗻 является и 𝗥𝗲𝗮𝗱𝗲𝗿, и 𝗪𝗿𝗶𝘁𝗲𝗿 (реализует методы интерфейса 𝗥𝗲𝗮𝗱([ ]𝗯𝘆𝘁𝗲) и 𝗪𝗿𝗶𝘁𝗲([ ]𝗯𝘆𝘁𝗲)).

После этого экземпляр 𝗖𝗼𝗻𝗻 передается в функцию обработки 𝗲𝗰𝗵𝗼(𝗻𝗲𝘁.𝗖𝗼𝗻𝗻). Перед ее вызовом указано ключевое слово 𝗴𝗼, делающее этот вызов многопоточным, в результате чего другие подключения в ожидании завершения функции-обработчика не блокируются. Это может показаться излишним для столь простого сервера, но мы добавили эту функциональность для демонстрации простоты паттерна многопоточности 𝗚𝗼 на случай, если вы еще не до конца его поняли. В данный момент у вас есть два легковесных параллельно выполняющихся потока.

  • Основной поток зацикливается и блокируется функцией listener.Accept() на время ожидания ею следующего подключения.

  • Горутина обработки, чье выполнение было передано в функцию echo(net.Conn), возобновляется и обрабатывает данные.


Далее показан пример использования 𝗧𝗲𝗹𝗻𝗲𝘁 в качестве подключающегося клиента:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Сервер производит следующий стандартный вывод:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост


Революционно, не правда ли? Сервер, возвращающий клиенту в точности то, что клиент ему отправил. Очень полезный и сильный пример!



Создание буферизованного слушателя для улучшения кода:



Пример в коде Базового эхо-сервера работает прекрасно, но он опирается на чисто низкоуровневые вызовы функции, отслеживание буфера и повторяющиеся циклы чтения/записи. Это довольно утомительный и подверженный ошибкам процесс. К счастью, в 𝗚𝗼 есть и другие пакеты, которые могут его упростить и уменьшить сложность кода. Говоря конкретнее, пакет 𝗯𝘂𝗳𝗶𝗼 обертывает 𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗪𝗿𝗶𝘁𝗲𝗿 для создания буферизованного механизма 𝗜/𝗢. Далее приведена обновленная функция 𝗲𝗰𝗵𝗼(𝗻𝗲𝘁.𝗖𝗼𝗻𝗻) с сопутствующим описанием изменений:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

В экземпляре 𝗖𝗼𝗻𝗻 больше не происходит прямого вызова функций 𝗥𝗲𝗮𝗱([]𝗯𝘆𝘁𝗲) и 𝗪𝗿𝗶𝘁𝗲([]𝗯𝘆𝘁𝗲). Вместо этого вы инициализируете новые буферизованные 𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗪𝗿𝗶𝘁𝗲𝗿 через 𝗡𝗲𝘄𝗥𝗲𝗮𝗱𝗲𝗿(𝗶𝗼.𝗥𝗲𝗮𝗱𝗲𝗿) и 𝗡𝗲𝘄𝗪𝗿𝗶𝘁𝗲𝗿(𝗶𝗼.𝗪𝗿𝗶𝘁𝗲𝗿). Оба вызова в качестве параметра получают существующие 𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗪𝗿𝗶𝘁𝗲𝗿 (помните, что тип 𝗖𝗼𝗻𝗻 реализует необходимые функции, чтобы считаться 𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗪𝗿𝗶𝘁𝗲𝗿).

Оба буферизованных экземпляра содержат вспомогательные функции для чтения и сохранения данных. 𝗥𝗲𝗮𝗱𝗦𝘁𝗿𝗶𝗻𝗴(𝗯𝘆𝘁𝗲) получает символ-разграничитель, обозначая, до какой точки выполнять считывание, а 𝗪𝗿𝗶𝘁𝗲𝗦𝘁𝗿𝗶𝗻𝗴(𝗯𝘆𝘁𝗲) записывает строку в сокет. При записи данных вам нужно явно вызывать 𝘄𝗿𝗶𝘁𝗲𝗿.𝗙𝗹𝘂𝘀𝗵() для сброса всех данных внутреннему райтеру (в данном случае экземпляру 𝗖𝗼𝗻𝗻).

Несмотря на то что предыдущий пример упрощает процесс, применяя буферизацию 𝗜/𝗢, вы можете переработать его под использование вспомогательной функции 𝗖𝗼𝗽𝘆(𝗪𝗿𝗶𝘁𝗲𝗿, 𝗥𝗲𝗮𝗱𝗲𝗿). Напомним, что функция получает в качестве ввода целевой 𝗪𝗿𝗶𝘁𝗲𝗿 и исходный 𝗥𝗲𝗮𝗱𝗲𝗿, просто выполняя копирование из источника в место назначения.

В этом примере вы передаете переменную 𝗰𝗼𝗻𝗻 и как источник, и как место назначения, так как в итоге будете отражать содержимое обратно в установленное соединение:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Вот вы и познакомились с основами системы 𝗜/𝗢, попутно применив ее к 𝗧𝗖𝗣-серверам. Пришло время перейти к более полезным и представляющим для вас интерес примерам.



Проксирование TCP-клиента:



Теперь, когда у вас под ногами есть твердая почва, можете применить полученные навыки для создания простого переадресатора портов для проксирования соединения через промежуточный сервис или хост. Как уже говорилось, это пригождается для обхода ограничивающего контроля исходящего трафика или использования системы с целью обхода сегментации сети. Прежде чем перейти к коду, рассмотрите вымышленную, но вполне реалистичную задачу: Андрей является малоэффективным сотрудником компании 𝗔𝗖𝗠𝗘 𝗜𝗻𝗰., работая на должности бизнес-аналитика и получая приличную зарплату просто потому, что слегка приукрасил данные своего резюме. (Неужели он реально учился в школе Лиги плюща? Андрей, такой обман неэтичен.) Недостаток мотивации Андрея может по силе сравниться разве что с его любовью к кошкам — такой сильной, что он даже установил дома специальные видеокамеры и создал сайт 𝗷𝗼𝗲𝘀𝗰𝗮𝘁𝗰𝗮𝗺.𝘄𝗲𝗯𝘀𝗶𝘁𝗲, через который удаленно следил за своими мохнатыми питомцами. Тем не менее здесь была одна сложность: 𝗔𝗖𝗠𝗘 следит за Андреем. Им не нравится, что он круглые сутки передает потоковое видео своих кошек в ультравысоком разрешении 𝟰𝗞, занимая ценный пропускной канал сети. Компания даже заблокировала своим сотрудникам возможность посещать его кошачий сайт.

Но у хитрого Андрея и здесь возник план: «А что, если я настрою переадресатор портов в подконтрольной мне интернет-системе и буду перенаправлять весь трафик с этого хоста на 𝗷𝗼𝗲𝘀𝗰𝗮𝘁𝗰𝗮𝗺.𝘄𝗲𝗯𝘀𝗶𝘁𝗲?» На следующий день Андрей отмечается на работе и убеждается в возможности доступа к личному сайту, размещенному на домене 𝗷𝗼𝗲𝘀𝗽𝗿𝗼𝘅𝘆.𝗰𝗼𝗺. Он пропускает все встречи после обеда и отправляется в кафетерий, где быстро пишет код для своей задачи, подразумевающей перенаправление на 𝗵𝘁𝘁𝗽://𝗷𝗼𝗲𝘀𝗰𝗮𝘁𝗰𝗮𝗺.𝘄𝗲𝗯𝘀𝗶𝘁𝗲 всего входящего на 𝗵𝘁𝘁𝗽://𝗷𝗼𝗲𝘀𝗽𝗿𝗼𝘅𝘆.𝗰𝗼𝗺 трафика.

Вот код Андрея, который он запускает на сервере 𝗷𝗼𝗲𝘀𝗽𝗿𝗼𝘅𝘆.𝗰𝗼𝗺:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Начнем с рассмотрения функции 𝗵𝗮𝗻𝗱𝗹𝗲(𝗻𝗲𝘁.𝗖𝗼𝗻𝗻). Андрей подключается к 𝗷𝗼𝗲𝘀𝗰𝗮𝘁𝗰𝗮𝗺.𝘄𝗲𝗯𝘀𝗶𝘁𝗲 (вспомните, что этот хост недоступен напрямую с его рабочего места). Затем он использует 𝗖𝗼𝗽𝘆(𝗪𝗿𝗶𝘁𝗲𝗿, 𝗥𝗲𝗮𝗱𝗲𝗿) в двух разных местах. Первый экземпляр обеспечивает копирование данных из входящего соединения в соединение 𝗷𝗼𝗲𝘀𝗰𝗮𝘁𝗰𝗮𝗺.𝘄𝗲𝗯𝘀𝗶𝘁𝗲. Второй же обеспечивает, чтобы считанные из 𝗷𝗼𝗲𝘀𝗰𝗮𝘁𝗰𝗮𝗺.𝘄𝗲𝗯𝘀𝗶𝘁𝗲 данные записывались обратно в соединение подключающегося клиента. Так как 𝗖𝗼𝗽𝘆(𝗪𝗿𝗶𝘁𝗲𝗿, 𝗥𝗲𝗮𝗱𝗲𝗿) является блокирующей функцией и будет продолжать блокировать выполнение, пока сетевое соединение открыто, Андрей предусмотрительно обертывает первый вызов 𝗖𝗼𝗽𝘆(𝗪𝗿𝗶𝘁𝗲𝗿, 𝗥𝗲𝗮𝗱𝗲𝗿) в новую горутину. Это гарантирует продолжение выполнения в функции 𝗵𝗮𝗻𝗱𝗹𝗲(𝗻𝗲𝘁.𝗖𝗼𝗻𝗻) и дает возможность выполнить второй вызов 𝗖𝗼𝗽𝘆(𝗪𝗿𝗶𝘁𝗲𝗿, 𝗥𝗲𝗮𝗱𝗲𝗿).

Прокси-сервер Андрей прослушивает порт 𝟴𝟬 и ретранслирует весь трафик, получаемый через это соединение, на порт 𝟴𝟬 сайта 𝗷𝗼𝗲𝘀𝗰𝗮𝘁𝗰𝗮𝗺.𝘄𝗲𝗯𝘀𝗶𝘁𝗲 и обратно. Этот безумный и расточительный парень убеждается, что может подключаться к 𝗷𝗼𝗲𝘀𝗰𝗮𝘁𝗰𝗮𝗺.𝘄𝗲𝗯𝘀𝗶𝘁𝗲 через 𝗷𝗼𝗲𝘀𝗽𝗿𝗼𝘅𝘆.𝗰𝗼𝗺 с помощью 𝗰𝘂𝗿𝗹:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Так Андрей успешно реализует коварный замысел. Он прекрасно устроился, получив возможность в оплачиваемое 𝗔𝗖𝗠𝗘 время использовать их же канал связи для наблюдения за жизнью своих питомцев.



Воспроизведение функции Netcat для выполнения команд:



В этом разделе мы воспроизведем одну из наиболее интересных функций 𝗡𝗲𝘁𝗰𝗮𝘁 — «зияющую дыру в безопасности».

𝗡𝗲𝘁𝗰𝗮𝘁 — это как швейцарский армейский нож для 𝗧𝗖𝗣/𝗜𝗣, который представляет собой более гибкую версию 𝗧𝗲𝗹𝗻𝗲𝘁 с поддержкой сценариев. Эта утилита имеет возможность перенаправлять 𝘀𝘁𝗱𝗶𝗻 и 𝘀𝘁𝗱𝗼𝘂𝘁 любой произвольной программы через 𝗧𝗖𝗣, позволяя атакующему, например, превратить уязвимость к выполнению одной команды в доступ к оболочке операционной системы. Взгляните:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Эта команда создает прослушивающий сервер на порте 𝟭𝟯𝟯𝟯𝟳. Любой подключающийся, возможно, через 𝗧𝗲𝗹𝗻𝗲𝘁, клиент сможет выполнить любые команды 𝗯𝗮𝘀𝗵 — вот почему данную функцию и называют зияющей дырой в безопасности. 𝗡𝗲𝘁𝗰𝗮𝘁 позволяет при желании включить такую возможность в процессе компиляции программы. (По понятным причинам большинство исполняемых файлов 𝗡𝗲𝘁𝗰𝗮𝘁 в стандартных сборках 𝗟𝗶𝗻𝘂𝘅 ее не включают.) Эта функция настолько потенциально опасна, что мы покажем, как воссоздать ее в 𝗚𝗼.

Для начала загляните в пакет 𝗚𝗼 𝗼𝘀/𝗲𝘅𝗲𝗰. Он будет использоваться для выполнения команд операционной системы. Этот пакет определяет тип 𝗖𝗺𝗱, который содержит необходимые методы и свойства для выполнения команд и управления 𝘀𝘁𝗱𝗶𝗻 и 𝘀𝘁𝗱𝗼𝘂𝘁. Вы будете перенаправлять 𝘀𝘁𝗱𝗶𝗻 (𝗥𝗲𝗮𝗱𝗲𝗿) и 𝘀𝘁𝗱𝗼𝘂𝘁 (𝗪𝗿𝗶𝘁𝗲𝗿) в экземпляр 𝗖𝗼𝗻𝗻, представляющий и 𝗥𝗲𝗮𝗱𝗲𝗿, и 𝗪𝗿𝗶𝘁𝗲𝗿.

При получении нового подключения создать экземпляр 𝗖𝗺𝗱 можно с помощью функции 𝗖𝗼𝗺𝗺𝗮𝗻𝗱(𝗻𝗮𝗺𝗲 𝘀𝘁𝗿𝗶𝗻𝗴, 𝗮𝗿𝗴 ...𝘀𝘁𝗿𝗶𝗻𝗴) из 𝗼𝘀/𝗲𝘅𝗲𝗰. Эта функция получает в качестве параметров команды ОС и любые аргументы. В данном примере нужно жестко закодировать в качестве команды /𝗯𝗶𝗻/𝘀𝗵 и передать в качестве аргумента -𝗶, чтобы перейти в интерактивный режим, из которого можно будет управлять потоками 𝘀𝘁𝗱𝗶𝗻 и 𝘀𝘁𝗱𝗼𝘂𝘁 более уверенно:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Эта инструкция создает экземпляр 𝗖𝗺𝗱, но команду еще не выполняет. Здесь для управления 𝘀𝘁𝗱𝗶𝗻 и 𝘀𝘁𝗱𝗼𝘂𝘁 есть два варианта: использовать 𝗖𝗼𝗽𝘆(𝗪𝗿𝗶𝘁𝗲𝗿, 𝗥𝗲𝗮𝗱𝗲𝗿), как говорилось ранее, или напрямую присвоить 𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗪𝗿𝗶𝘁𝗲𝗿 экземпляру 𝗖𝗺𝗱. Давайте непосредственно присвоим объект 𝗖𝗼𝗻𝗻 экземплярам 𝗰𝗺𝗱.𝗦𝘁𝗱𝗶𝗻 и 𝗰𝗺𝗱.𝗦𝘁𝗱𝗼𝘂𝘁:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

После настройки команды и потоков запустить ее можно с помощью 𝗰𝗺𝗱.𝗥𝘂𝗻():

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Такая логика прекрасно работает для систем 𝗟𝗶𝗻𝘂𝘅. Тем не менее при настройке и запуске этой программы под 𝗪𝗶𝗻𝗱𝗼𝘄𝘀 с помощью 𝗰𝗺𝗱.𝗲𝘅𝗲, а не /𝗯𝗶𝗻/𝗯𝗮𝘀𝗵, подключающийся клиент не получает вывод команды из-за специфичной для 𝗪𝗶𝗻𝗱𝗼𝘄𝘀 обработки анонимных каналов. Далее описаны два решения этой проблемы.

Во-первых, можно настроить код для принудительного сброса 𝘀𝘁𝗱𝗼𝘂𝘁. Вместо непосредственного присваивания 𝗖𝗼𝗻𝗻 экземпляру 𝗰𝗺𝗱.𝗦𝘁𝗱𝗼𝘂𝘁 нужно реализовать собственный 𝗪𝗿𝗶𝘁𝗲𝗿, который обертывает 𝗯𝘂𝗳𝗶𝗼.𝗪𝗿𝗶𝘁𝗲𝗿 (буферизованный райтер) и явно вызывает его метод 𝗙𝗹𝘂𝘀𝗵 для принудительного сброса буфера. Пример использования 𝗯𝘂𝗳𝗶𝗼.𝗪𝗿𝗶𝘁𝗲𝗿 можно найти в разделе «Создание эхо-сервера» ранее в этой главе. Вот определение пользовательского райтера, 𝗙𝗹𝘂𝘀𝗵𝗲𝗿:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Тип 𝗙𝗹𝘂𝘀𝗵𝗲𝗿 реализует функцию 𝗪𝗿𝗶𝘁𝗲([]𝗯𝘆𝘁𝗲), которая записывает данные во внутренний буферизованный райтер, а затем сбрасывает вывод.

С помощью этой реализации пользовательского райтера можно настроить обработчик подключений на создание экземпляра и применение типа 𝗙𝗹𝘂𝘀𝗵𝗲𝗿 для 𝗰𝗺𝗱.𝗦𝘁𝗱𝗼𝘂𝘁:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Продолжение кода выше

Это решение хотя и вполне пригодно, но не очень элегантно. Несмотря на то что рабочий код для нас важнее, чем аккуратный, мы используем эту проблему как возможность рассказать о функции 𝗶𝗼.𝗣𝗶𝗽𝗲(). Она представляет собой синхронный канал в памяти 𝗚𝗼, который можно задействовать для подключения 𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗪𝗿𝗶𝘁𝗲𝗿:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Применение 𝗣𝗶𝗽𝗲𝗥𝗲𝗮𝗱𝗲𝗿 и 𝗣𝗶𝗽𝗲𝗪𝗿𝗶𝘁𝗲𝗿 позволяет избежать необходимости явного сброса райтера и синхронного подключения 𝘀𝘁𝗱𝗼𝘂𝘁 и 𝗧𝗖𝗣-соединения. Опять же понадобится переписать функцию обработчика:

Создание TCP-прокси Информационная безопасность, Хакеры, Программирование, Golang, Программист, Интернет, Длиннопост

Вызов 𝗶𝗼.𝗣𝗶𝗽𝗲 создает ридер и райтер, подключаемые синхронно, — любые данные, записываемые в райтер (в данном примере 𝘄𝗽), будут считаны ридером (𝗿𝗽). Поэтому сначала происходит присваивание райтера экземпляру 𝗰𝗺𝗱.𝗦𝘁𝗱𝗼𝘂𝘁, после чего используется 𝗶𝗼.𝗖𝗼𝗽𝘆(𝗰𝗼𝗻𝗻, 𝗿𝗽) для присоединения 𝗣𝗶𝗽𝗲𝗥𝗲𝗮𝗱𝗲𝗿 к 𝗧𝗖𝗣-соединению. Это делается с помощью горутины, предотвращающей блокирование кода. Любой стандартный вывод команды отправляется райтеру, после чего передается ридеру и далее через 𝗧𝗖𝗣-соединение. Как вам такая элегантность?

Таким образом, мы успешно реализовали «зияющую дыру безопасности» 𝗡𝗲𝘁𝗰𝗮𝘁 с позиции 𝗧𝗖𝗣-слушателя, ожидающего подключения. По тому же принципу можно реализовать эту функцию с позиции подключающегося клиента, перенаправляющего 𝘀𝘁𝗱𝗼𝘂𝘁 и 𝘀𝘁𝗱𝗶𝗻 локального исполняемого файла удаленному слушателю. Детали этого процесса мы оставим вам для самостоятельной реализации, но в общем они будут включать следующее:

  • установку подключения к удаленному слушателю через net.Dial(network, address string);

  • инициализацию Cmd через exec.Command(name string, arg ...string);

  • перенаправление свойств Stdin и Stdout для использования объекта net.Conn;

  • выполнение команды.

На этом этапе слушатель должен получить подключение. Любые передаваемые клиенту данные должны интерпретироваться на клиенте как 𝘀𝘁𝗱𝗶𝗻, а данные, получаемые слушателем, — как 𝘀𝘁𝗱𝗼𝘂𝘁.

На этом всё, ждите в ближайшее время больше статей.

ССЫЛКА НА ТЕЛЕГРАМ КАНАЛ АВТОРА

Показать полностью 21
[моё] Информационная безопасность Хакеры Программирование Golang Программист Интернет Длиннопост
0
6
PENTEST.DNA
PENTEST.DNA
1 год назад
Web-технологии

TCP, сканеры и прокси⁠⁠

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

В роли атакующего вы должны понимать принцип работы 𝗧𝗖𝗣, чтобы справляться с разработкой пригодных вариантов его конструкций, позволяющих определять открытые/закрытые порты, распознавать такие потенциально ошибочные результаты, как ложные срабатывания — например, 𝗦𝗬𝗡-флуд защиты, — и обходить ограничения на исходящий трафик посредством переадресации портов. В этой главе вы изучите основы 𝗧𝗖𝗣-коммуникаций в 𝗚𝗼, реализуете многопоточный правильно отрегулированный сканер портов, создадите 𝗧𝗖𝗣-прокси, который можно использовать для переадресации портов, а также воссоздадите 𝗡𝗲𝘁𝗰𝗮𝘁-функцию «зияющая дыра в безопасности».

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

TCP Handshaking:



В качестве напоминания мы начнем с основ. снизу будет показано, как 𝗧𝗖𝗣 при запросе порта использует процесс рукопожатия (𝗵𝗮𝗻𝗱𝘀𝗵𝗮𝗸𝗶𝗻𝗴), определяя, открыт порт, закрыт или фильтруется.

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Основы рукопожатия в TCP


Если порт открыт, рукопожатие осуществляется в три этапа. Сначала клиент отправляет пакет 𝘀𝘆𝗻, определяющий начало сеанса связи. В ответ на это сервер отправляет 𝘀𝘆𝗻-𝗮𝗰𝗸, иначе говоря, подтверждение получения пакета 𝘀𝘆𝗻, предлагая клиенту завершить сеанс установки связи отправкой сигнала 𝗮𝗰𝗸, то есть встречного подтверждения получения ответа сервера. После этого может начаться обмен данными. Если же порт будет закрыт, сервер ответит пакетом 𝗿𝘀𝘁, а не 𝘀𝘆𝗻-𝗮𝗰𝗸. В случае, когда трафик фильтруется межсетевым экраном (брандмауэром), клиент обычно не получает от сервера ответа.

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



Обход брандмауэра с помощью переадресации портов:



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

Многие корпоративные сети ограничивают возможность подключения своих внутренних ресурсов к вредоносным сайтам. В качестве примера представьте такой сайт под названием 𝗲𝘃𝗶𝗹.𝗰𝗼𝗺. Если сотрудник компании попытается подключиться к нему напрямую, брандмауэр заблокирует его запрос. Но если у сотрудника есть собственная внешняя система, доступная через брандмауэр (например, 𝘀𝘁𝗮𝗰𝗸𝘁𝗶𝘁𝗮𝗻.𝗰𝗼𝗺), то он может задействовать ее для установки связи с 𝗲𝘃𝗶𝗹.𝗰𝗼𝗺. Этот принцип отражен снизу.

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

TCP-проски

Клиент подключается к удаленному хосту 𝘀𝘁𝗮𝗰𝗸𝘁𝗶𝘁𝗮𝗻.𝗰𝗼𝗺 через брандмауэр. Этот хост настроен на перенаправление соединений к хосту 𝗲𝘃𝗶𝗹.𝗰𝗼𝗺. Несмотря на то что брандмауэр запрещает прямые подключения к 𝗲𝘃𝗶𝗹.𝗰𝗼𝗺, описанная конфигурация позволяет клиенту обойти этот механизм защиты.

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



Написание TCP-сканера:



Один из эффективных способов концептуализировать понимание взаимодействия 𝗧𝗖𝗣-портов — это реализация их сканера. В процессе его создания вы увидите все шаги обмена рукопожатиями в 𝗧𝗖𝗣, а также эффекты от возникающих изменений состояний, которые позволяют определить, является ли порт доступным, закрытым или отфильтровывается.

Написав базовый сканер портов, вы перейдете к созданию его ускоренной версии. Базово эта программа способна сканировать множество портов, используя один непрерывный метод, но если вам потребуется выполнить сканирование всех 𝟲𝟱 𝟱𝟯𝟱 портов, это может занять слишком много времени. Поэтому мы научим вас с помощью многопоточности делать малоэффективный сканер более подходящим для выполнения задач расширенного сканирования. Освоенные в этой статье шаблоны параллельности вы сможете применять и во многих других сценариях.


Тестирование портов на доступность:


Первый шаг в создании сканера портов — понять процесс инициирования соединения от клиента к серверу. В рассматриваемом примере вы будете подключаться к 𝘀𝗰𝗮𝗻𝗺𝗲.𝗻𝗺𝗮𝗽.𝗼𝗿𝗴 — сервису проекта 𝗡𝗺𝗮𝗽𝟭 и сканировать его. Для этого мы с вами задействуем пакет 𝗚𝗼 𝗻𝗲𝘁: 𝗻𝗲𝘁.𝗗𝗶𝗮𝗹(𝗻𝗲𝘁𝘄𝗼𝗿𝗸, 𝗮𝗱𝗱𝗿𝗲𝘀𝘀 𝘀𝘁𝗿𝗶𝗻𝗴).

Первый аргумент — это строка, определяющая тип инициируемого соединения. Дело в том, что 𝗗𝗶𝗮𝗹 используется не только для 𝗧𝗖𝗣, но и для создания соединений, задействующих сокеты 𝗨𝗻𝗶𝘅, 𝗨𝗗𝗣 и протоколы 𝟰-го уровня, которые мы оставим в стороне, так как на основе всего нашего опыта будет достаточно просто сказать, что 𝗧𝗖𝗣 очень хорош. В этот аргумент можно передать несколько вариантов строк, но для краткости будем использовать строку 𝘁𝗰𝗽.

Второй аргумент указывает 𝗗𝗶𝗮𝗹(𝗻𝗲𝘁𝘄𝗼𝗿𝗸, 𝗮𝗱𝗱𝗿𝗲𝘀𝘀 𝘀𝘁𝗿𝗶𝗻𝗴) на хост, к которому вы хотите подключиться. Обратите внимание на то, что это одна строка, а не 𝘀𝘁𝗿𝗶𝗻𝗴 и 𝗶𝗻𝘁. Для соединений 𝗜𝗣𝘃𝟰/𝗧𝗖𝗣 она будет принимать форму 𝗵𝗼𝘀𝘁:𝗽𝗼𝗿𝘁. Например, если вам нужно подключиться к 𝘀𝗰𝗮𝗻𝗺𝗲.𝗻𝗺𝗮𝗽.𝗼𝗿𝗴 через 𝗧𝗖𝗣-порт 𝟴𝟬, то нужно указать 𝘀𝗰𝗮𝗻𝗺𝗲.𝗻𝗺𝗮𝗽.𝗼𝗿𝗴:𝟴𝟬.

Теперь вы знаете, как создать соединение, но как понять, что оно было успешным? Для этого выполняется проверка на ошибки: 𝗗𝗶𝗮𝗹(𝗻𝗲𝘁𝘄𝗼𝗿𝗸, 𝗮𝗱𝗱𝗿𝗲𝘀𝘀 𝘀𝘁𝗿𝗶𝗻𝗴) возвращает Conn и error. При этом error будет nil, если соединение установлено успешно. Так что для проверки вам просто нужно убедиться, что error равна nil. Вот теперь у вас есть все необходимые элементы для построения сканера портов, хотя и не особо корректного. В Основах рукопожатия в TCP показано, как все это объединить.

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Простой сканер портов, сканирующий только один порт /dial/main.go

Выполнив этот код, вы должны увидеть сообщение 𝗖𝗼𝗻𝗻𝗲𝗰𝘁𝗶𝗼𝗻 𝘀𝘂𝗰𝗰𝗲𝘀𝘀𝗳𝘂𝗹 при условии наличия у вас доступа к великой информационной супермагистрали


Выполнение однопоточного сканирования:



Сканирование по одному порту за раз не особо полезно и малоэффективно, так как диапазон 𝗧𝗖𝗣-портов — от 𝟭 до 𝟲𝟱 𝟱𝟯𝟱. В целях же тестирования давайте пока просканируем порты от 𝟭 до 𝟭𝟬𝟮𝟰. Для этого можно использовать цикл 𝗳𝗼𝗿:

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Теперь у вас есть 𝗶𝗻𝘁, но нужно помнить, что в качестве второго аргумента для 𝗗𝗶𝗮𝗹(𝗻𝗲𝘁𝘄𝗼𝗿𝗸, 𝗮𝗱𝗱𝗿𝗲𝘀𝘀 𝘀𝘁𝗿𝗶𝗻𝗴) требуется строка. Есть по меньшей мере два способа преобразования целого числа в строку. Первый — использовать пакет преобразования строк 𝘀𝘁𝗿𝗰𝗼𝗻𝘃. Второй — применить функцию 𝗦𝗽𝗿𝗶𝗻𝘁𝗳(𝗳𝗼𝗿𝗺𝗮𝘁 𝘀𝘁𝗿𝗶𝗻𝗴, 𝗮 ...𝗶𝗻𝘁𝗲𝗿𝗳𝗮𝗰𝗲{}) из пакета 𝗳𝗺𝘁, которая (аналогично своему собрату в 𝗖) возвращает 𝘀𝘁𝗿𝗶𝗻𝗴, сгенерированную из строки формата (𝗳𝗼𝗿𝗺𝗮𝘁 𝘀𝘁𝗿𝗶𝗻𝗴).


Создайте файл с кодом из листинга 𝟮.𝟮 и убедитесь в работоспособности цикла и функции генерации строки. Выполнение этого кода должно вывести 𝟭𝟬𝟮𝟰 строки, но утруждать себя их подсчетом не обязательно.

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Сканирование 1024 портов scanme.nmap.org /tcp-scanner-slow/main.go

Теперь осталось только подставить переменную адреса из предыдущего кода в 𝗗𝗶𝗮𝗹(𝗻𝗲𝘁𝘄𝗼𝗿𝗸, 𝗮𝗱𝗱𝗿𝗲𝘀𝘀 𝘀𝘁𝗿𝗶𝗻𝗴) и протестировать доступность портов, реализовав такую же проверку ошибок, как в предыдущем разделе. Помимо этого, чтобы не оставлять успешные соединения открытыми, следует добавить логику их закрытия. Завершение соединений — это жест вежливости. Для этого вам нужно выполнить в 𝗖𝗼𝗻𝗻 вызов 𝗖𝗹𝗼𝘀𝗲(). Снизу показана полноценная реализация сканера портов.

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Завершенный сканер портов /tcp-scanner-slow/main.go

Скомпилируйте и выполните этот код для выполнения легкого сканирования цели. Вы должны обнаружить пару открытых портов.



Параллельное сканирование:



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



Слишком быстрая версия сканера:



Самым прямолинейным способом создания параллельного сканера будет обернуть вызов 𝗗𝗶𝗮𝗹(𝗻𝗲𝘁𝘄𝗼𝗿𝗸, 𝗮𝗱𝗱𝗿𝗲𝘀𝘀 𝘀𝘁𝗿𝗶𝗻𝗴) в горутину. Чтобы собственными глазами увидеть последствия этого, создайте файл 𝘀𝗰𝗮𝗻-𝘁𝗼𝗼-𝗳𝗮𝘀𝘁.𝗴𝗼 с кодом который снизу.

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Сканер, работающий слишком быстро /tcp-scanner-too-fast/main.go

При выполнении кода вы заметите, что программа завершается практически мгновенно:

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Этот код запускает по одной горутине для каждого соединения, а основная горутина не знает, что нужно ждать окончания его установки. В связи с этим выполнение кода завершается, как только цикл 𝗳𝗼𝗿 заканчивает перебор, что происходит быстрее, чем сеть успевает осуществить обмен пакетами между кодом и всеми целевыми портами. Поэтому вы не получите точных результатов для портов, чьи пакеты находились в процессе обмена.


Исправить это можно несколькими способами. Первый — использовать 𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽 из пакета 𝘀𝘆𝗻𝗰, предоставляющий потокобезопасный способ управления параллельным выполнением. 𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽 — это тип структуры, который создается так:

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Создав 𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽, вы можете вызвать для этой структуры несколько методов. Первый метод — 𝗔𝗱𝗱(𝗶𝗻𝘁), увеличивающий внутренний счетчик согласно переданному числу. Следующий — метод 𝗗𝗼𝗻𝗲(), уменьшающий счетчик на 𝟭. И наконец, метод 𝗪𝗮𝗶𝘁(), блокирующий выполнение горутины, в которой вызывается, запрещая дальнейЭтот вариант кода по большому счету остался неизменным. Тем не менее здесь мы добавили код, явно отслеживающий оставшуюся работу. В этой версии программышее выполнение, пока внутренний счетчик не достигнет нуля. Эти вызовы можно совмещать, гарантируя, что основная горутина дождется завершения всех соединений.


Синхронизированное сканирование с помощью WaitGroup:

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Синхронизированный сканер, использующий WaitGroup /tcp-scanner-wg-too-fast/main.go

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

создаем 𝘀𝘆𝗻𝗰.𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽, выступающую в качестве синхронизированного счетчика. Мы увеличиваем этот счетчик через 𝘄𝗴.𝗔𝗱𝗱(𝟭) при каждом создании горутины для сканирования порта. При этом отложенный вызов 𝘄𝗴.𝗗𝗼𝗻𝗲() уменьшает этот счетчик при завершении каждой единицы работы. Функция 𝗺𝗮𝗶𝗻() вызывает 𝘄𝗴.𝗪𝗮𝗶𝘁(), который блокирует выполнение, пока не будет выполнена вся работа и счетчик не достигнет нуля.

Эта версия программы уже лучше, но по-прежнему имеет недостатки. Если запустить ее несколько раз для разных хостов, можно получить несогласованные результаты. Одновременное сканирование чрезмерного количества хостов или портов может привести к тому, что ограничения системы или сети исказят результаты. Попробуйте изменить в коде значение 𝟭𝟬𝟮𝟰 на 𝟲𝟱𝟱𝟯𝟱 и укажите адрес целевого сервера как 𝟭𝟮𝟳.𝟬.𝟬.𝟭. При желании можете использовать 𝗪𝗶𝗿𝗲𝘀𝗵𝗮𝗿𝗸 или 𝘁𝗰𝗽𝗱𝘂𝗺𝗽, чтобы увидеть, насколько быстро открываются эти соединения.



Сканирование портов с помощью пула воркеров:



Чтобы избежать несогласованности, можно задействовать для управления параллельным выполнением пул горутин. С помощью цикла 𝗳𝗼𝗿 вы создаете определенное количество воркеров горутин в качестве пула. Затем в потоке 𝗺𝗮𝗶𝗻() с помощью канала обеспечиваете работу.

Для начала создайте новую программу, которая использует канал 𝗶𝗻𝘁, содержит 𝟭𝟬𝟬 воркеров и выводит их результаты на экран. При этом задействуйте 𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽 для блокирования выполнения.

Создайте начальную заглушку кода для функции 𝗺𝗮𝗶𝗻, а над ней напишите функцию,приведенную в коде ниже

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Функция с воркером для выполнения задачи.

Функция 𝘄𝗼𝗿𝗸𝗲𝗿(𝗶𝗻𝘁, *𝘀𝘆𝗻𝗰.𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽) получает два аргумента: канал типа 𝗶𝗻𝘁 и указатель на 𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽. Канал будет использоваться для получения работы, а 𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽 — для отслеживания завершения одной ее единицы.

Далее добавьте функцию 𝗺𝗮𝗶𝗻(), приведенную в коде ниже, которая будет управлять рабочей нагрузкой и обеспечивать работу функции 𝘄𝗼𝗿𝗸𝗲𝗿(𝗶𝗻𝘁, *𝘀𝘆𝗻𝗰.𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽).

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Базовый пул воркеров /tcp-sync-scanner/main.go

Сначала создается канал с помощью 𝗺𝗮𝗸𝗲(). В 𝗺𝗮𝗸𝗲() в качестве второго параметра передается значение 𝟭𝟬𝟬. Это добавляет каналу буферизацию, то есть в него можно будет отправлять элемент и не ждать, пока получатель этот элемент прочтет. Буферизованные каналы идеально подходят для поддержания и отслеживания работы нескольких производителей и потребителей. Емкость канала определяется как 𝟭𝟬𝟬. Значит, он может вместить 𝟭𝟬𝟬 элементов, до того как отправитель будет заблокирован. Это дает небольшой прирост производительности, поскольку все воркеры смогут запускаться сразу.

Далее с помощью цикла 𝗳𝗼𝗿 запускается заданное число воркеров — в данном случае 𝟭𝟬𝟬. В функции 𝘄𝗼𝗿𝗸𝗲𝗿(𝗶𝗻𝘁, *𝘀𝘆𝗻𝗰.𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽) с помощью 𝗿𝗮𝗻𝗴𝗲 происходит непрерывное циклическое получение данных из канала 𝗽𝗼𝗿𝘁𝘀, завершающееся только при закрытии канала. Обратите внимание: пока воркер никакой работы не выполняет — это произойдет чуть позже. Последовательно перебирая порты в функции 𝗺𝗮𝗶𝗻(), вы отправляете порт через канал 𝗽𝗼𝗿𝘁𝘀 воркеру. По завершении всей работы закрываете канал.

Запустив эту программу, вы увидите, как на экран выводятся числа. Здесь можно заметить кое-что интересное, а именно то, что выводятся они в конкретном порядке. Добро пожаловать в прекрасный мир многопоточности!



Многоканальная связь:



Чтобы завершить создание сканера, можно вставить код, использованный ранее в этом разделе, и это вполне сработает. Но в таком случае выводимые порты будут не отсортированы, так как сканер станет проверять их не по порядку. Решить эту проблему можно, реализовав упорядоченную передачу результатов сканирования в основной поток через дополнительный. Это изменение к тому же позволит полностью устранить зависимость от 𝗪𝗮𝗶𝘁𝗚𝗿𝗼𝘂𝗽, так как теперь у вас будет другой метод для отслеживания завершения. Например, если вы сканируете 𝟭𝟬𝟮𝟰 порта, то делаете по каналу воркера 𝟭𝟬𝟮𝟰 передачи, после чего снова выполняете 𝟭𝟬𝟮𝟰 передачи с результатами работы обратно в основной поток. Поскольку количество отправленных единиц работы и полученных результатов совпадает, программа понимает, когда нужно закрывать каналы и, следовательно, отключать воркеры.


Эта модификация кода представлена в коде ниже, которым завершается создание сканера.

TCP, сканеры и прокси Программирование, Информационная безопасность, Хакеры, Golang, IT, Программист, Длиннопост

Сканирование портов через несколько каналов /tcp-scanner-final/main.go

Функция 𝘄𝗼𝗿𝗸𝗲𝗿(𝗽𝗼𝗿𝘁𝘀, 𝗿𝗲𝘀𝘂𝗹𝘁𝘀 𝗰𝗵𝗮𝗻 𝗶𝗻𝘁) была изменена для получения двух каналов. Остальная логика почти полностью осталась прежней, за исключением того, что в случае закрытого порта вы отправляете ноль, а в случае открытого — значение этого порта. Кроме того, здесь вы создаете отдельный канал для передачи результатов от воркера в основной поток. Затем результаты сохраняются в срез, что позволяет выполнить их сортировку. Далее вам нужно реализовать отправку данных воркера в отдельной горутине, потому что цикл сбора результатов должен начаться до того, как сможет продолжиться выполнение более 𝟭𝟬𝟬 единиц работы.

Этот цикл получает по каналу 𝗿𝗲𝘀𝘂𝗹𝘁𝘀 𝟭𝟬𝟮𝟰 передачи. Если порт не равен 𝟬, он добавляется в срез. После закрытия каналов вы используете сортировку для упорядочивания среза открытых портов. Далее остается лишь перебрать срез и вывести открытые порты на экран.

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

В полученную программу можно внести пару улучшений. Во-первых, вы отправляете по каналу 𝗿𝗲𝘀𝘂𝗹𝘁𝘀 результат сканирования каждого порта, что необязательно. Альтернативное решение потребует написания более сложного кода, который будет использовать дополнительный канал не только для отслеживания воркеро. Вам может потребоваться, чтобы сканер умел парсить строки с портами, например 𝟴𝟬,𝟰𝟰𝟯,𝟴𝟬𝟴𝟬,𝟮𝟭-𝟮𝟱, наподобие тех, что могут быть переданы в 𝗡𝗺𝗮𝗽. Я предлагаю вам освоить этот прием самостоятельно.

P.S: в следующей статье мы рассмотрим создание TCP-прокси.

ССЫЛКА НА ТЕЛЕГРАМ КАНАЛ АВТОРА

Показать полностью 13
[моё] Программирование Информационная безопасность Хакеры Golang IT Программист Длиннопост
1
4
PENTEST.DNA
PENTEST.DNA
1 год назад
Web-технологии

Создание майнера данных⁠⁠

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

ИНФОРМАЦИЯ ИСКЛЮЧИТЕЛЬНО ДЛЯ ОЗНАКОМЛЕНИЯ!!


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

Интерфейс должен быть минимальным, то есть состоять из нескольких базовых типов и функций, требуя реализации всего одного метода для извлечения схемы базы данных. В коде ниже определяется именно такой интерфейс майнера с названием 𝗱𝗯𝗺𝗶𝗻𝗲𝗿.𝗴𝗼.

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

Реализация майнера данных /db/dbminer/dbminer.go

Код начинается с определения интерфейса DatabaseMiner. Для реализующих этот интерфейс типов будет требоваться один-единственный метод — GetSchema(). Поскольку каждая серверная база данных может иметь собственную логику для извлечения данной схемы, подразумевается, что каждая конкретная утилита сможет реализовать эту логику уникальным для используемых БД и драйвера способом.

Далее мы определяем тип 𝗦𝗰𝗵𝗲𝗺𝗮, состоящий из нескольких подтипов, которые определены здесь же. Тип 𝗦𝗰𝗵𝗲𝗺𝗮 задействуется для логического представления схемы БД, то есть баз данных, таблиц и столбцов. Вы могли обратить внимание на то, что функция 𝗚𝗲𝘁𝗦𝗰𝗵𝗲𝗺𝗮() в определении интерфейса ожидает, что реализации вернут *𝗦𝗰𝗵𝗲𝗺𝗮.

Далее идет определение одной функции 𝗦𝗲𝗮𝗿𝗰𝗵() с объемной логикой. Эта функция ожидает передачи экземпляра 𝗗𝗮𝘁𝗮𝗯𝗮𝘀𝗲𝗠𝗶𝗻𝗲𝗿 и сохраняет значение майнера в переменной 𝗺. Начинается она с вызова 𝗺.𝗚𝗲𝘁𝗦𝗰𝗵𝗲𝗺𝗮() для извлечения схемы. Затем функция перебирает всю эту схему в поиске списка соответствующих значений регулярному выражению (𝗿𝗲𝗴𝗲𝘅). При нахождении соответствий схема базы данных и совпадающие поля выводятся на экран.

В завершение мы определяем функцию 𝗴𝗲𝘁𝗥𝗲𝗴𝗲𝘅(). Она компилирует строки регулярных выражений с помощью пакета 𝗚𝗼 𝗿𝗲𝗴𝗲𝘅𝗽 и возвращает срез их значений. Список 𝗿𝗲𝗴𝗲𝘅 состоит из нечувствительных к регистру строк, которые сопоставляются со стандартными или интересующими нас именами полей, например 𝗰𝗰𝗻𝘂𝗺, 𝘀𝘀𝗻 и 𝗽𝗮𝘀𝘀𝘄𝗼𝗿𝗱.

Теперь, имея в распоряжении интерфейс добытчика, можно создать особые реализации утилит. Начнем с добытчика данных из 𝗠𝗼𝗻𝗴𝗼𝗗𝗕.



Реализация майнера данных из MongoDB:


Утилита для работы с MongoDB, показанная в коде ниже, реализует интерфейс из кода Реализации майнера данных, а также интегрирует код подключения к базе данных, который я написал в предыдущем посте (Подключение к базе данных MongoDB).

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

Создание майнера для MongoDB /db/mongo/main.go

Вначале мы импортируем пакет 𝗱𝗯𝗺𝗶𝗻𝗲𝗿, определяющий интерфейс 𝗗𝗮𝘁𝗮𝗯𝗮𝘀𝗲𝗠𝗶𝗻𝗲𝗿. Затем прописываем тип 𝗠𝗼𝗻𝗴𝗼𝗠𝗶𝗻𝗲𝗿, который будет использоваться для реализации этого интерфейса. Для удобства также реализуется функция 𝗡𝗲𝘄(), создающая новый экземпляр типа 𝗠𝗼𝗻𝗴𝗼𝗠𝗶𝗻𝗲𝗿, вызывая метод 𝗰𝗼𝗻𝗻𝗲𝗰𝘁(), который устанавливает подключение к базе данных. В совокупности эта логика производит начальную загрузку кода, выполняя подключение к базе данных аналогичным рассмотренному в листинге 𝟳.𝟲 способом.

Самая интересная часть кода содержится в реализации метода интерфейса 𝗚𝗲𝘁𝗦𝗰𝗵𝗲𝗺𝗮(). В отличие от примера кода 𝗠𝗼𝗻𝗴𝗼𝗗𝗕 из кода (Предыдущий Пост) Подключение к базе данных MongoDB и запрос данных , теперь мы проверяем метаданные 𝗠𝗼𝗻𝗴𝗼𝗗𝗕, сначала извлекая имена баз данных, а затем перебирая эти базы данных для получения имен коллекции каждой. В завершение эта функция получает сырой документ, который, в отличие от типичного запроса 𝗠𝗼𝗻𝗴𝗼𝗗𝗕, использует отложенный демаршалинг. Это позволяет явно демаршалировать запись в общую структуру и проверить имена полей. Если бы не возможность такого отложенного демаршалинга, пришлось бы определять явный тип, скорее всего, использующий атрибуты тега 𝗯𝘀𝗼𝗻, инструктируя программу о порядке демаршалинга данных в определенную нами структуру. В этом случае мы не знаем о типах полей или структуре (или нам все равно), нам просто нужны имена полей (не данные) — именно так можно демаршалировать структурированные данные, не зная структуры заранее.

Функция 𝗺𝗮𝗶𝗻() ожидает 𝗜𝗣-адрес экземпляра 𝗠𝗼𝗻𝗴𝗼𝗗𝗕 в качестве единственного аргумента, вызывает функцию 𝗡𝗲𝘄() для начальной загрузки всего, после чего вызывает 𝗱𝗯𝗺𝗶𝗻𝗲𝗿.𝗦𝗲𝗮𝗿𝗰𝗵(), передавая ему экземпляр 𝗠𝗼𝗻𝗴𝗼𝗠𝗶𝗻𝗲𝗿. Напомним, что 𝗱𝗯𝗺𝗶𝗻𝗲𝗿.𝗦𝗲𝗮𝗿𝗰𝗵() вызывает 𝗚𝗲𝘁𝗦𝗰𝗵𝗲𝗺𝗮() в полученном экземпляре 𝗗𝗮𝘁𝗮𝗯𝗮𝘀𝗲𝗠𝗶𝗻𝗲𝗿. Таким образом происходит вызов реализации функции 𝗠𝗼𝗻𝗴𝗼𝗠𝗶𝗻𝗲𝗿, что приводит к созданию 𝗱𝗯𝗺𝗶𝗻𝗲𝗿.𝗦𝗰𝗵𝗲𝗺𝗮, которая затем просматривается на соответствие списку 𝗿𝗲𝗴𝗲𝘅 из кода Реализация майнера данных.

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

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

Разобравшись с реализацией для MongoDB, в следующем разделе сделаем то же самое для серверной базы данных MySQL.



Реализация майнера для MySQL




Чтобы реализация 𝗠𝘆𝗦𝗤𝗟 заработала, мы будем проверять таблицу 𝗶𝗻𝗳𝗼𝗿𝗺𝗮𝘁𝗶𝗼𝗻_𝘀𝗰𝗵𝗲𝗺𝗮.𝗰𝗼𝗹𝘂𝗺𝗻𝘀. Она содержит метаданные обо всех базах данных и их структурах, включая таблицы и имена столбцов. Чтобы максимально упростить потребление данных, используйте приведенный далее 𝗦𝗤𝗟-запрос. Он удалит информацию о некоторых из встроенных БД 𝗠𝘆𝗦𝗤𝗟, не имеющих для нас значения:

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

В результате данного запроса вы получите примерно такие результаты:

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

Несмотря на то что использовать этот запрос для извлечения информации схемы довольно просто, сложность кода обусловливается стремлением логически дифференцировать и категоризировать каждую строку при определении функции GetSchema(). Например, последовательные строки вывода могут принадлежать или не принадлежать одной базе данных/таблице, поэтому ассоциирование строк с правильными экземплярами dbminer.Database и dbminer.Table становится несколько запутанным.

В коде снизу показана реализация:

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

Создание майнера для MySQL /db/mysql/main.go/

Бегло просмотрев код, вы можете заметить, что большая его часть очень похожа на пример для MongoDB из предыдущего раздела. В частности, идентична функция main().

Функции начальной загрузки также очень похожи — изменяется лишь логика на взаимодействие с MySQL, а не MongoDB. Обратите внимание на то, что эта логика подключается к базе данных information.schema, позволяя проинспектировать схему базы данных.

Основная сложность этого кода заключена в реализации 𝗚𝗲𝘁𝗦𝗰𝗵𝗲𝗺𝗮(). Несмотря на то что мы можем извлечь информацию схемы, используя один запрос к БД, после приходится перебирать результаты, просматривая каждую строку с целью определения присутствующих баз данных, их таблиц и строк этих таблиц. В отличие от реализации для 𝗠𝗼𝗻𝗴𝗼𝗗𝗕, у нас нет преимущества 𝗝𝗦𝗢𝗡/𝗕𝗦𝗢𝗡 с тегами атрибутов для маршалинга и демаршалинга данных в сложные структуры. Мы используем переменные для отслеживания информации в текущей строке и сравниваем ее с данными из предыдущей строки, чтобы понять, когда встретим новую базу данных или таблицу. Не самое изящное решение, но с задачей справляется.

Далее идет проверка соответствия имен баз данных текущей и предыдущей строк. Если они совпадают, создается новый экземпляр 𝗺𝗶𝗻𝗲𝗿.𝗗𝗮𝘁𝗮𝗯𝗮𝘀𝗲. Если это не первая итерация цикла, таблица и база данных добавляются в экземпляр 𝗺𝗶𝗻𝗲𝗿.𝗦𝗰𝗵𝗲𝗺𝗮. С помощью аналогичной логики мы отслеживаем и добавляем экземпляры 𝗺𝗶𝗻𝗲𝗿.𝗧𝗮𝗯𝗹𝗲 в текущую 𝗺𝗶𝗻𝗲𝗿𝗗𝗮𝘁𝗮𝗯𝗮𝘀𝗲. В завершение каждый столбец добавляется в 𝗺𝗶𝗻𝗲𝗿.𝗧𝗮𝗯𝗹𝗲.

Теперь запустите готовую программу в отношении экземпляра 𝗗𝗼𝗰𝗸𝗲𝗿 𝗠𝘆𝗦𝗤𝗟, чтобы убедиться в корректности ее работы:

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

Вывод должен получиться практически идентичным выводу для 𝗠𝗼𝗻𝗴𝗼𝗗𝗕. Причина в том, что 𝗱𝗯𝗺𝗶𝗻𝗲𝗿.𝗦𝗰𝗵𝗲𝗺𝗮 не производит никакого вывода — это делает функция 𝗱𝗯𝗺𝗶𝗻𝗲𝗿.𝗦𝗲𝗮𝗿𝗰𝗵(). В этом заключается сила интерфейсов. Можно использовать конкретные реализации ключевых возможностей, задействуя при этом одну стандартную функцию для обработки данных прогнозируемым эффективным способом. В следующем разделе мы отойдем от БД и рассмотрим кражу данных из файловых систем.

Получение данных из файловых систем:



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

Данная утилита просматривает именно имена файлов, а не их содержимое. При этом скрипт существенно упрощается тем, что пакет Go path/filepath предоставляет стандартную функциональность, с помощью которой можно эффективно обходить структуру каталогов. Сама утилита приведена в коде ниже.

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

Обход файловой системы /filesystem/main.go

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

Далее идет определение функции walkFn(), которая принимает путь файла и ряд дополнительных параметров. Эта функция перебирает список регулярных выражений в поиске совпадений, которые выводит в stdout. Функция walkFn() используется в функции main() и передается в качестве параметра в filepath.Walk(). Walk() ожидает два параметра — корневой путь и функцию (в данном случае walkFn()) — и рекурсивно обходит структуру каталогов, начиная с переданного корневого пути и попутно вызывая walkFn() для каждого встречающегося каталога и файла.

Написав утилиту, перейдите на рабочий стол и создайте следующую структуру каталогов:

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

Выполнение утилиты в отношении той же папки targetpath производит следующий вывод, подтверждая, что код работает исправно:

Создание майнера данных Информационная безопасность, Программирование, Интернет, Golang, Взлом, Хакеры, Длиннопост

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

ССЫЛКА НА ТЕЛЕГРАМ КАНАЛ АВТОРА

Показать полностью 11
[моё] Информационная безопасность Программирование Интернет Golang Взлом Хакеры Длиннопост
5
0
PENTEST.DNA
PENTEST.DNA
1 год назад
Web-технологии

Подключение к базам данных и запрос информации с помощью Go⁠⁠

Подключение к базам данных и запрос информации с помощью Go Информационная безопасность, Хакеры, Golang, Программирование, Безопасность, IT, Взлом, Программист, Длиннопост

Запрос данных из MongoDBL:


Несмотря на наличие прекрасного стандартного 𝗦𝗤𝗟-пакета, 𝗚𝗼 не поддерживает аналогичный пакет для работы с базами данных 𝗡𝗼𝗦𝗤𝗟. Для этого вам придется использовать сторонние инструменты. Вместо изучения реализации каждого такого стороннего пакета мы сосредоточимся исключительно на 𝗠𝗼𝗻𝗴𝗼𝗗𝗕. Для этого будем применять драйвер 𝗺𝗴𝗼 (произносится «манго»). Начните с установки 𝗺𝗴𝗼:

Подключение к базам данных и запрос информации с помощью Go Информационная безопасность, Хакеры, Golang, Программирование, Безопасность, IT, Взлом, Программист, Длиннопост

Теперь можно установить подключение и запросить коллекцию 𝘀𝘁𝗼𝗿𝗲 (эквивалент таблицы), для чего потребуется еще меньше кода, чем в примере с 𝗦𝗤𝗟, который мы создадим чуть позже.

Подключение к базам данных и запрос информации с помощью Go Информационная безопасность, Хакеры, Golang, Программирование, Безопасность, IT, Взлом, Программист, Длиннопост

Подключение к базе данных MongoDB и запрос данных

Сначала идет определение типа 𝗧𝗿𝗮𝗻𝘀𝗮𝗰𝘁𝗶𝗼𝗻, который будет представлять один документ из коллекции 𝘀𝘁𝗼𝗿𝗲. Внутренний механизм представления данных в 𝗠𝗼𝗻𝗴𝗼𝗗𝗕 — это двоичный 𝗝𝗦𝗢𝗡. По этой причине для определения любых директив маршалинга используются теги. В этом случае с их помощью мы явно определяем имена элементов для применения в двоичных данных 𝗝𝗦𝗢𝗡.

В функции 𝗺𝗮𝗶𝗻() вызов 𝗺𝗴𝗼.𝗗𝗶𝗮𝗹() создает сессию, устанавливая подключение к базе данных, выполняя тестирование на наличие ошибок и реализуя отложенный вызов для закрытия сессии. После этого с помощью переменной 𝘀𝗲𝘀𝘀𝗶𝗼𝗻 запрашивается база данных 𝘀𝘁𝗼𝗿𝗲, откуда извлекаются все записи коллекции 𝘁𝗿𝗮𝗻𝘀𝗮𝗰𝘁𝗶𝗼𝗻𝘀. Результаты мы сохраняем в срезе 𝗧𝗿𝗮𝗻𝘀𝗮𝗰𝘁𝗶𝗼𝗻 под названием 𝗿𝗲𝘀𝘂𝗹𝘁𝘀. Теги структуры используются для демаршалинга двоичного 𝗝𝗦𝗢𝗡 в определенный нами тип. В завершение выполняется перебор результатов и их вывод на экран. И в этом случае, и в примере с 𝗦𝗤𝗟 из следующего раздела вывод должен выглядеть так:

Подключение к базам данных и запрос информации с помощью Go Информационная безопасность, Хакеры, Golang, Программирование, Безопасность, IT, Взлом, Программист, Длиннопост


Обращение к базам данных SQL:



𝗚𝗼 содержит стандартный пакет 𝗱𝗮𝘁𝗮𝗯𝗮𝘀𝗲/𝘀𝗾𝗹, который определяет интерфейс для взаимодействия с базами данных 𝗦𝗤𝗟 и их аналогами. Базовая реализация автоматически включает такую функциональность, как пул подключений и поддержка транзакций. Драйверы базы данных, соответствующие этому интерфейсу, автоматически наследуют эти возможности и, по сути, являются взаимозаменяемыми, поскольку 𝗔𝗣𝗜 между ними остается согласованным. Вызовы функций и реализация в коде идентичны независимо от того, используете вы 𝗣𝗼𝘀𝘁𝗴𝗿𝗲𝘀, 𝗠𝗦𝗦𝗤𝗟, 𝗠𝘆𝗦𝗤𝗟 или другой драйвер. В результате этого удобно менять серверные базы данных при минимальном изменении кода клиента. Конечно же, эти драйверы могут реализовывать специфичные для БД возможности и задействовать различный 𝗦𝗤𝗟-синтаксис, но вызовы функций при этом практически одинаковы. Поэтому мы покажем, как подключать всего одну базу данных 𝗦𝗤𝗟 — 𝗠𝘆𝗦𝗤𝗟, а остальные БД 𝗦𝗤𝗟 оставим в качестве самостоятельного упражнения. Начнем с установки драйвера:

Подключение к базам данных и запрос информации с помощью Go Информационная безопасность, Хакеры, Golang, Программирование, Безопасность, IT, Взлом, Программист, Длиннопост

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

Подключение к базам данных и запрос информации с помощью Go Информационная безопасность, Хакеры, Golang, Программирование, Безопасность, IT, Взлом, Программист, Длиннопост

Код начинается с импорта пакета 𝗚𝗼 𝗱𝗮𝘁𝗮𝗯𝗮𝘀𝗲/𝘀𝗾𝗹. Это позволяет реализовать взаимодействие с базой данных через удобный интерфейс стандартной библиотеки 𝗦𝗤𝗟. Кроме того, мы импортируем драйвер базы данных. Начальное подчеркивание указывает на то, что она импортируется анонимно, то есть ее экспортируемые типы не включаются, но драйвер регистрируется пакетом 𝘀𝗾𝗹, и в результате драйвер 𝗠𝘆𝗦𝗤𝗟 сам обрабатывает вызовы функций.

Далее идет вызов 𝘀𝗾𝗹.𝗢𝗽𝗲𝗻() для установки подключения к базе данных. Первый параметр указывает, какой драйвер использовать — в данном случае это 𝗺𝘆𝘀𝗾𝗹, а второй определяет строку подключения. Затем мы обращаемся к базе данных, передавая инструкцию 𝗦𝗤𝗟 для выбора всех строк из таблицы 𝘁𝗿𝗮𝗻𝘀𝗮𝗰𝘁𝗶𝗼𝗻𝘀, после чего перебираем эти строки, последовательно считывая данные в переменные и выводя значения.

Это все, что необходимо для запроса данных из 𝗠𝘆𝗦𝗤𝗟. Для использования другой серверной БД потребуется внести в код лишь минимальные изменения:

  • импортировать подходящий драйвер базы данных;

  • изменить передаваемые в sql.Open() параметры;

  • скорректировать SQL-синтаксис в соответствии с требованиями серверной базы данных.

Среди нескольких доступных драйверов баз данных часть написаны на чистом 𝗚𝗼. А некоторые другие используют 𝗰𝗴𝗼 для ряда внутренних взаимодействий. Полный список доступных драйверов можно найти здесь: 𝗵𝘁𝘁𝗽𝘀://𝗴𝗶𝘁𝗵𝘂𝗯.𝗰𝗼𝗺/𝗴𝗼𝗹𝗮𝗻𝗴/𝗴𝗼/𝘄𝗶𝗸𝗶/𝗦𝗤𝗟𝗗𝗿𝗶𝘃𝗲𝗿𝘀/.

ССЫЛКА НА ТЕЛЕГРАМ КАНАЛ АВТОРА

Показать полностью 5
[моё] Информационная безопасность Хакеры Golang Программирование Безопасность IT Взлом Программист Длиннопост
0
PENTEST.DNA
PENTEST.DNA
1 год назад

Написание DNS-клиентов⁠⁠

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Прежде чем начать знакомство с более сложными программами, рассмотрим ряд опций, доступных для клиентских операций. Встроенный в Go пакет net предлагает обширную функциональность и поддерживает большинство, если не все типы записей. Преимущество этого пакета — в простоте его API. Например, LookupAddr(addr string) возвращает список имен хостов для заданного IP-адреса. Недостаток же его заключается в невозможности указывать целевой сервер. Вместо этого пакет использует настроенный в операционной системе механизм распознавания. К недостаткам можно отнести также отсутствие возможности выполнения углубленного анализа результатов.

Для обхода этих недочетов мы задействуем отличный сторонний пакет Go DNS, написанный Миком Гибеном (Miek Gieben). Предпочесть этот DNS-пакет всем прочим стоит из-за его высокой модульности и грамотно написанного и протестированного кода. Вот команда для его установки:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

$ go get github.com/miekg/dns

Установив пакет, вы будете готовы к проработке последующих примеров кода. Начнем с выполнения поиска А-записей для получения IP-адресов из имен хостов.


Извлечение А-записей:

Сперва познакомимся с поиском для полностью уточненного имени домена (fully qualified domain name, FQDN), которое указывает точное расположение хоста в иерархии DNS. Затем попробуем интерпретировать это FQDN в IP-адрес с помощью DNS-записи А. Эта запись связывает имя домена с IP-адресом. (Все листинги кода находятся в корневом каталоге /exist репозитория GitHub https://github.com/blackhat-go/bhg/.)

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Код на языке Golang

Сначала создается msg , после чего идет вызов fqdn(string) для преобразования этого домена в FQDN, которым можно обменяться с DNS-сервером . Далее нужно изменить внутреннее состояние Msg на вызов SetQuestion(string, uint16)

с помощью значения TypeA, указывающего, что нужно искать А-запись. (В пакете она определена как const. Другие поддерживаемые значения можно найти в документации.) В завершение мы помещаем вызов Exchange(*Msg, string) , чтобы отправить сообщение на предоставленный адрес сервера, в данном случае являющегося DNS-сервером, обслуживаемым Google.

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

Перед выполнением программы которая написана выше запустите анализатор пакетов, например Wireshark или tcpdump, чтобы просмотреть трафик. Вот пример возможного использования tcpdump на хосте Linux:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

$ sudo tcpdump -i eth0 -n udp port 53

В отдельном окне терминала скомпилируйте и выполните программу:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

$ go run main.go

После выполнения кода в выходных данных перехвата пакетов должны отобразиться подключение к 8.8.8.8 через UDP 53, а также детали DNS-протокола:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Две из получаемых при перехвате пакетов строчек нуждаются в дополнительном пояснении. Сначала запрос отправляется с 192.168.7.51 к 8.8.8.8 с помощью UDP 53, при этом происходит запрос А-записи. В ответе от DNS-сервера Google 8.8.8.8 содержится интерпретированный из имени домена IP-адрес 104.131.56.170.

С помощью анализатора пакетов можно преобразовать имя домена stacktitan.com в IP-адрес. Теперь посмотрим, как извлечь эту информацию, используя Go.


Отработка ответов от структуры Msg:


В качестве значения Exchange(*Msg, string) возвращает (*Msg, error). Возврат типа error имеет смысл и является стандартным для идиом Go, но почему в ответе приходит также изначально отправленная *Msg? Чтобы это понять, нужно взглянуть на определение этой struct в исходном коде:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Код на языке Golang

Как видите, Msg struct содержит как вопросы (question), так и ответы (answer). Это позволяет объединять все DNS-вопросы и ответы на них в единую унифицированную структуру. Тип Msg располагает различными методами, упрощающими работу с данными. Например, срез Question изменяется с помощью метода setQuestion(). Это срез можно изменять напрямую, используя append(), и получать тот же результат. Срез Answer содержит ответ на запросы и имеет тип RR. Ниже будет показано, как эти ответы обрабатывать.

Обработка DNS-ответов:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Пример начинается с сохранения возвращенных от Exchange значений и их проверки на наличие ошибок. Если ошибка обнаружена, вызывается panic() для остановки программы. Функция panic() позволяет быстро просмотреть трассировку стека и определить место возникновения ошибки. Далее проверяется длина среза Answer. Если она меньше 1, это означает, что записей нет, и происходит возврат — бывают случаи, когда имя домена не может быть интерпретировано.

Тип RR является интерфейсом, имеющим всего два определенных метода, ни один из которых не дает доступа к IP-адресу, хранящемуся в ответе. Для доступа к этим адресам нужно применить утверждение типа, чтобы создать экземпляр данных в качестве нужного типа.

Сначала выполняем перебор ответов. Далее применяем в ответе утверждение типа, чтобы гарантировать работу с типом *dns.A. При выполнении этого действия можно извлечь два значения: данные в виде утвержденного типа и bool, отражающее успешность утверждения. После проверки успешности утверждения происходит вывод IP, сохраненного в a.A. Несмотря на тип net.IP, он реализует метод String(), поэтому его можно легко вывести на экран.

Поработайте с этим кодом, изменяя DNS-запрос и обмен (exchange) для поиска дополнительных записей. Утверждение типа может оказаться для вас незнакомым, но по своему принципу оно аналогично приведению типов в других языках.


Перечисление поддоменов:


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

Используя DNS, можно отправлять запросы настолько быстро, насколько быстро система сможет обрабатывать пакеты данных. Узким местом здесь станут не язык или среда выполнения, а сервер назначения. При этом, как и в предыдущих главах, будет важно управление многопоточностью программы.

Сначала нужно создать в GOPATH каталог под названием subdomain_guesser, а затем файл main.go. После этого в начале создания нового инструмента необходимо решить, какие аргументы эта программа будет получать. В данном случае это будет несколько аргументов, включая целевой домен, имя файла, содержащего поддомены для подбора, используемый DNS-сервер, а также количество запускаемых воркеров. В Go для парсинга опций командной строки есть полезный пакет flag, который мы будем применять для обработки аргументов командной строки. Несмотря на то что мы используем этот пакет не во всех примерах кода, в данном случае он служит для демонстрации более надежного и изящного парсинга аргументов. Код этого процесса будет приведен ниже.

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Создание программы подбора поддоменов на языке Golang

В начале строка кода, объявляющая переменную flDomain, получает аргумент String и объявляет пустое строковое значение для того, что будет парситься как опция domain. Следующая связанная строка — это объявление переменной flWorkerCount. Здесь в качестве опции командной строки c нужно предоставить значение Integer. В данном случае мы устанавливаем 100 воркеров. Но это значение можно счесть консервативным, так что в процессе тестирования смело экспериментируйте с увеличением их числа. В завершение вызов flag.Parse() заполняет переменные, задействуя предоставленный пользователем ввод.


ПРИМЕЧАНИЕ:


Вы могли обратить внимание на то, что этот пример идет вразрез с правилами Unix в том, что определяет необязательные аргументы, которые на деле являются обязательными. Можете свободно использовать здесь os.Args. Просто нам быстрее и удобнее поручить всю работу пакету flag.

При сборке данной программы должна возникнуть ошибка, указывающая на неиспользованные переменные. Добавьте приведенный далее код сразу после вызова flag.Parse(). Это дополнение выводит в stdout переменные наряду с кодом,
гарантируя передачу пользователем -domain и -wordlist:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Чтобы ваш инструмент сообщал, какие имена оказались интерпретируемыми, указывая при этом соответствующие им IP-адреса, нужно создать для хранения этой информации тип struct. Определите его над функцией main():

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Для этого инструмента вы будете запрашивать два основных типа записей — А и CNAME. Каждый запрос будет выполняться в отдельной функции. Стоит создавать эти функции максимально небольшими и поручать каждой выполнение только одной задачи. Такой стиль разработки позволит в дальнейшем писать менее объемные тесты.


Запрос записей A и CNAME:


Для выполнения запросов мы создадим две функции: одну для А-записей, вторую для записей CNAME. Они обе будут получать FQDN в качестве первого аргумента и адрес DNS-сервера в качестве второго. Каждая из них должна возвращать срез строк и ошибку. Добавьте эти функции в код, который начали определять, расположив вне области main():

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Этот код должен показаться вам знакомым, так как он практически идентичен коду, который мы писали в самом начале главы. Первая функция, lookupA, возвращает список IP-адресов, а lookupCNAME возвращает список имен хостов.

Записи CNAME (канонические имена) сопоставляют одно FQDN с другим, которое служит псевдонимом для первого. Предположим, что владелец организации example.com хочет разместить WordPress-сайт с помощью сервиса хостинга WordPress. У этого сервиса могут быть сотни IP-адресов для балансировки всех пользовательских сайтов, в связи с чем предоставить IP для отдельного сайта просто невозможно. Вместо этого данный хостинг может предоставить каноническое имя (CNAME), на которое и будет ссылаться example.com. В итоге адрес www.example.com получит CNAME, указывающее на somewhere.hostingcompany.org, которое, в свою очередь, будет иметь А-запись, указывающую на IP-адрес. Это позволит владельцу example.com разместить свой сайт на сервере, для которого у него нет IP-данных.

Зачастую это означает, что вам нужно проследить целый хвост из канонических имен, чтобы в итоге добраться до действительной А-записи. Мы говорим хвост, потому что из подобных имен может выстраиваться бесконечная цепочка. Добавьте приведенный далее код функции в область за пределами функции main(), чтобы понаблюдать, как использовать череду CNAMES для нахождения А-записи:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Сначала определяется срез для хранения результатов. Далее создается копия FQDN, переданного в качестве первого аргумента. В итоге вы не только не теряете исходный угаданный FQDN, но и можете задействовать его в первой попытке запроса. Начав бесконечный цикл, мы пробуем получить CNAME для этого FQDN. В случае отсутствия ошибок и возвращения не менее одного CNAME устанавливаем cfqdn равным этому возвращенному CNAME, используя continue для возврата к началу цикла. Данный процесс позволяет проследить череду CNAME до возникновения сбоя. Последний будет означать, что конец цепочки достигнут и можно искать А-записи. Но если возникнет ошибка, означающая, что при поиске записи возникли проблемы, то выход из цикла произойдет раньше. В случае обнаружения действительных А-записей каждый возвращенный IP-адрес добавляется в срез результатов, а цикл прерывается. В завершение results возвращается вызывающему.

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


Переход к воркер-функции:


Мы создадим пул горутин, которые будут передавать работу воркер-функции, выполняющей единицу работы. Для распределения работы и сбора ее результатов задействуем каналы. Напомним, что нечто подобное мы уже делали в главе 2, когда создавали многопоточный сканер портов.

Продолжим расширять код Создание программы подбора поддоменов. Сначала создадим функцию worker(), разместив ее вне области функции main(). Она будет получать три аргумента каналов: канал для воркера, чтобы он сигнализировал о своем закрытии, канал доменов, в которых нужно получать работу, и канал для отправки результатов. Этой функции потребуется заключительный строковый аргумент для указания используемого DNS-сервера. Далее приведен пример кода для функции worker():

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Прежде чем вводить функцию worker(), определим тип empty для отслеживания завершения выполнения воркера. Это будет структура без полей. Мы задействуем пустую struct, так как она имеет размер 0 байт и практически не создаст нагрузку при использовании. Далее в функции worker() происходит перебор канала доменов, используемый для передачи FQDN. После получения ответа от функции lookup() и проверки наличия не менее одного результата мы отправляем его в канал gather, который собирает все результаты обратно в main(). После того как канал закрывается и цикл совершает выход, структура empty отправляет в канал tracker сигнал вызывающему о завершении всей работы. Отправка пустой struct в канал отслеживания — это важный последний шаг. Если этого не сделать, возникнет состояние гонки, так как вызывающий компонент может выйти до получения каналом gather результатов.

Поскольку вся необходимая структура теперь настроена, можно переключиться обратно на main() и закончить программу, которую мы начали писать в Создание программы подбора поддоменов.

Определите переменные, которые будут содержать результаты и каналы, передаваемые в worker(), после чего добавьте в main() следующий код:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Создайте канал fqdns как буферизованный на основе предоставленного пользователем количества воркеров. Это позволит воркерам запускаться быстрее, поскольку канал сможет вместить больше одного сообщения до блокировки отправителя.


Создание сканера с помощью bufio:


Далее откройте файл, предоставленный пользователем в качестве списка слов, и создайте в нем новый scanner с помощью пакета bufio. Добавьте в main() код

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Если возвращаемая ошибка не равна nil, используется встроенная функция panic(). При написании пакета или программы для применения другими людьми следует постараться представить эту информацию более ясно.

Мы будем применять новый scanner для захвата строки текста из переданного списка слов и создания FQDN путем совмещения этого текста с предоставленным пользователем доменом. Результат будет отправляться в канал fqdns. Но сначала нужно запустить воркеры, так как порядок важен. Если отправить работу в канал fqdns, не запустив их, этот буферизованный канал в итоге заполнится и функции-производители будут заблокированы. В main() нужно добавить приведенный далее код, чья задача — запускать горутины воркеров, читать вводный файл и отправлять работу в канал fqdns.

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Создание воркеров с помощью этого паттерна похоже на то, что мы уже делали при построении многопоточного сканера портов: задействовали цикл for до момента достижения числа, переданного пользователем. Для захвата каждой строки в цикле используется scanner.Scan(). Этот цикл заканчивается, когда в файле не остается строк для считывания. Для получения строкового представления текста из отсканированной строки мы применяем scanner.Text().

Работа запущена! Отвлекитесь на секунду и ощутите свое величие. Прежде чем читать следующий код, подумайте, где вы находитесь в программе и что уже успели сделать за время чтения книги. Попробуйте самостоятельно закончить эту программу и затем перейти к следующему разделу, где мы поясним ее оставшуюся часть.

Сбор и отображение результатов

Проработку последней части мы начнем с запуска анонимной горутины, которая будет собирать результаты воркеров. Добавьте в main() следующее:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Перебирая канал gather, мы добавляем полученные результаты в срез results. Поскольку мы добавляем срез в другой срез, нужно использовать синтаксис … . После закрытия канала gather и завершения перебора, как и прежде, происходит отправка пустой struct в канал отслеживания. Это делается для предотвращения состояния гонки на случай, если append() не завершится к моменту итогового предоставления результатов пользователю.

Остается только закрыть каналы и представить результаты. Для этого добавьте следующий код в конец main():

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Первым можно закрыть канал fqdns, так как мы уже отправили по нему всю работу. Далее нужно выполнить получение результатов в канале tracker по одному разу для каждого воркера, что позволит им обозначить свое полное завершение. После этого можно закрыть канал gather, потому что результатов для получения не остается. В завершение нужно выполнить еще одно получение результатов на канале tracker, чтобы позволить горутине окончательно завершиться.

Эти результаты пользователю еще не представлены. Нужно это исправить. При желании можно просто перебрать срез results и вывести поля Hostname и IPAddress, используя fmt.Printf(). Тем не менее мы предпочитаем задействовать для представления данных один из нескольких прекрасных пакетов Go, а именно tabwriter. Он позволяет выводить данные в красивых ровных столбцах, разбитых на вкладки. Для его применения добавьте в конец main() следующий код:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)


Снизу показана вся программа в сборе:

Package main

import (

"bufio"

"errors"

"flag"

"fmt"

"os"

"text/tabwriter"

"github.com/miekg/dns"

)

func lookupA(fqdn, serverAddr string) ([]string, error) {

var m dns.Msg

var ips []string

m.SetQuestion(dns.Fqdn(fqdn), dns.TypeA)

in, err := dns.Exchange(&m, serverAddr)

if err != nil {

return ips, err

}

if len(in.Answer) < 1 {

return ips, errors.New("no answer")

}

for _, answer := range in.Answer {

if a, ok := answer.(*dns.A); ok {

ips = append(ips, a.A.String())

}

}

return ips, nil

}

func lookupCNAME(fqdn, serverAddr string) ([]string, error) {

var m dns.Msg

var fqdns []string

m.SetQuestion(dns.Fqdn(fqdn), dns.TypeCNAME)

in, err := dns.Exchange(&m, serverAddr)

if err != nil {

return fqdns, err

}

if len(in.Answer) < 1 {

return fqdns, errors.New("no answer")

}

for _, answer := range in.Answer {

if c, ok := answer.(*dns.CNAME); ok {

fqdns = append(fqdns, c.Target)

}

}

return fqdns, nil

}

func lookup(fqdn, serverAddr string) []result {

var results []result

var cfqdn = fqdn // Не изменяем оригинал

For {

cnames, err := lookupCNAME(cfqdn, serverAddr)

if err == nil && len(cnames) > 0 {

cfqdn = cnames[0]

continue // Нужно обработать следующее CNAME

}

ips, err := lookupA(cfqdn, serverAddr)

if err != nil {

break // Для этого имени хоста нет А-записей

}

for _, ip := range ips {

results = append(results, result{IPAddress: ip, Hostname: fqdn})

}

break // Все результаты обработаны

}

return results

}

func worker(tracker chan empty, fqdns chan string, gather chan []result,

serverAddr string) {

for fqdn := range fqdns {

results := lookup(fqdn, serverAddr)

if len(results) > 0 {

gather <- results

}

}

var e empty

tracker <- e

}

type empty struct{}

type result struct {

IPAddress string

Hostname string

}

func main() {

var (

flDomain = flag.String("domain", "", "The domain to perform

guessing against.")

flWordlist = flag.String("wordlist", "", "The wordlist to use

for guessing.")

flWorkerCount = flag.Int("c", 100, "The amount of workers to use.")

flServerAddr = flag.String("server", "8.8.8.8:53", "The DNS server

to use.")

)

flag.Parse()

if *flDomain == "" || *flWordlist == "" {

fmt.Println("-domain and -wordlist are required")

os.Exit(1)

}

var results []result

fqdns := make(chan string, *flWorkerCount)

gather := make(chan []result)

tracker := make(chan empty)

fh, err := os.Open(*flWordlist)

if err != nil {

panic(err)

}

defer fh.Close()

scanner := bufio.NewScanner(fh)

for I := 0; i < *flWorkerCount; i++ {

go worker(tracker, fqdns, gather, *flServerAddr)

}

go func() {

for r := range gather {

results = append(results, I.)

}

var e empty

tracker <- e

}()

for scanner.Scan() {

fqdns <- fmt.Sprintf"%s.%", scanner.Text(), *flDomain)

}

// Заметьте: здесь можно проверить scanner.Err()

close(fqdns)

for i := 0; i < *flWorkerCount; i++ {

<-tracker

}

close(gather)

<-tracker

w := tabwriter.NewWriter(os.Stdout, 0, 8' ', ' ', 0)

for _, r := range results {

fmt.Fprint"(w, "%s\"%s\n", r.Hostname, r.IPAddress)

}

w.Flush()

}


На этом наша программа для подбора поддоменов готова. Теперь вы можете собрать и запустить этот инструмент. Опробуйте его на списках слов или словарях из открытых репозиториев (можете найти множество через Google). Поэкспериментируйте с количеством воркеров. Вы можете заметить, что при слишком быстрой обработке результаты получаются неоднозначные. Вот пример выполнения с использованием ста воркеров:

Написание DNS-клиентов Хакеры, Программирование, Информационная безопасность, Взлом, Программист, Linux, IT, Google, Golang, Пентест, Длиннопост, Telegram (ссылка)

Вы увидите, что вывод показывает несколько FQDN и их IP-адреса. Мы смогли угадать значения поддоменов для каждого результата на основе списка слов, переданного в качестве вводного файла.

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

ССЫЛКА НА ТЕЛЕГРАМ КАНАЛ АВТОРА

Показать полностью 20
Хакеры Программирование Информационная безопасность Взлом Программист Linux IT Google Golang Пентест Длиннопост Telegram (ссылка)
1
5
egorgasay
egorgasay
1 год назад

Идеальное тестирование Golang кода⁠⁠

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

Описание библиотеки:

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

Преимущества и особенности:

  1. Тестирование с реальными зависимостями: Библиотека "dockerdb" позволяет разработчикам проводить тестирование баз данных с реальными зависимостями, включая другие сервисы или компоненты системы. Это позволяет более точно смоделировать реальную среду и выявить потенциальные проблемы.

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

  3. Гибкость и простота использования: Библиотека "dockerdb" предоставляет простой и гибкий интерфейс для развертывания и управления базами данных в контейнерах Docker. Она поддерживает различные СУБД, такие как MySQL, PostgreSQL, MongoDB и другие.

Идеальное тестирование Golang кода Golang, Docker, Длиннопост

На картинке представлена не самая возможная короткая запись для честности. Поднять базу данных популярного вендора можно гораздо проще:

Идеальное тестирование Golang кода Golang, Docker, Длиннопост

Заключение:

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

Попробовать:

https://github.com/egorgasay/dockerdb

Показать полностью 2
[моё] Golang Docker Длиннопост
0
Блог компании
Finder
Finder
1 год назад

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO⁠⁠

Язык Golang, который был разработан корпорацией Google еще в 2007 году, представляет собой аналог С++ и решает множество задач в программной инженерии. Его главная особенность — многозадачность и работа на базе компилируемого языка с упрощенным стабильным синтаксисом. Он поддерживает сборку мусора, что позволяет эффективно управлять памятью на устройстве. Программисты полагают, что в скором времени этот язык программирования займет лидирующую позицию. Golang курсы — это возможность уже сейчас получить перспективную профессию будущего.

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний

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

ТОП-10 лучших курсов по Golang в 2024 году

  1. Golang Developer. Professional от OTUS — лучший курс обучения до уровня Middle.

  2. Курс Разработка на Go от GeekBrains — лучший курс для обучения на junior-уровне.

  3. Курс «Go-разработчик» от Яндекс Практикум — лучший курс для опытных разработчиков.

  4. Профессия Backend-разработчик на Go от Skillfactory — лучший курс для погружения в профессию.

  5. Golang Developer. Basic от OTUS.ru — лучший курс для старта в языке.

  6. Курс Разработчик Golang. Professional от OTUS.ru — лучший углубленный курс.

  7. Golang для инженеров от Слёрм — лучший курс для инженеров с опытом

  8. Изучение языка Golang от itProger — лучший курс для создания своего первого веб-сайта.

  9. Очный курс Go-разработчик от Бруноям — лучший экспресс-курс.

  10. Чистая архитектура приложения на GO от Слёрм — лучший курс для знакомства с инструментами языка Go.

  11. Онлайн-практикум Golang-разработчик. Advanced от Rebrain — лучший практический курс.

Курсы по языку Go подойдут для тех, кто только пришел в сферу IT или уже имеет небольшой опыт в разработке. Если вы выбираете курс не для новичков, то учтите, что вам понадобятся определенные навыки или знания. Те, кто с успехом освоят программирование, смогут создавать приложения, сервисы и даже попробовать себя в роли администратора баз данных. А еще это возможность для продвижения по карьерной лестнице.

Онлайн-курсы по Golang

1. Golang Developer. Professional I OTUS

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

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: от 121 000 руб.

  • Длительность: 5 месяцев

  • Формат обучения: вебинары, теория, практика, проектная работа.

  • Сертификат: сертификат или диплом о профессиональной переподготовке

Преимущества курса:

  • регулярно проводятся бесплатные открытые вебинары;

  • интерактивные вебинары 2 раза в неделю;

  • активное комьюнити;

  • приобретение навыков на уровне middle специалиста;

  • возможность пройти собеседование у партнеров курса.

Недостатки курса:

  • серьезные требования для начала обучения;

  • редкий старт занятий;

  • требуется пройти вступительное тестирование.

Программа обучения:

  • Начало работы с Go.

  • Concurrency в Go.

  • Стандартные библиотеки и практики.

  • Работа с сетью и БД.

  • Микросервисы.

  • Проект.

Ознакомиться с полной программой курса >>>

2. Курс Разработка на Go | GeekBrains

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

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: 408 744 руб.

  • Длительность: 12 месяцев

  • Формат обучения: видеоуроки, вебинары, практика

  • Сертификат: диплом о профессиональной переподготовке

Преимущества курса:

  • универсальные навыки с использованием продвинутых инструментов;

  • программа разработана с учетом нулевых знаний в IT;

  • повышение своей ценности на рынке труда;

  • более 50 практических заданий;

  • подойдет для специалистов из смежных профессий;

  • возможность найти работу уже через 9 месяцев обучения;

  • программа постоянно обновляется с учетом новых требований на рынке.

Недостатки курса:

  • необходимость знания английского языка;

  • эксперты долго отвечают на вопросы учеников.

Программа обучения:

  • Введение в программирования.

  • Знакомство с базами данных.

  • Информатика и математика для программистов.

  • Знакомство с языком Python и Java.

  • База данных и SQL.

  • Архитектура ПО.

  • Контейнеризация.

  • Парадигмы программирования.

Ознакомиться с полной программой курса >>>

3.Курс «Go-разработчик»| Яндекс Практикум

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

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: от 144 000 руб.

  • Длительность: 6 месяцев

  • Формат обучения: вебинары, теория, практика, помощь менторов

  • Сертификат: сертификат или диплом о профессиональной переподготовке

Преимущества курса:

  • выбор уровня нагрузки, длительности курса и дедлайнов;

  • подготовка трех проектов с чистого листа;

  • сбор портфолио;

  • помощь в трудоустройстве;

  • навыки написания сложных приложений;

  • помощь от опытных разработчиков;

  • возможность работать с языком высокой производительности и масштабируемости.

Недостатки курса:

  • необходимы навыки бэкенд-разработки и языка программирования Go;

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

Программа обучения:

  • Введение в процесс обучения.

  • Стандартная библиотека.

  • Конкурентность.

  • Паттерны проектирования.

  • Туллинг.

  • Алгоритмы и структуры данных.

Ознакомиться с полной программой курса >>>

4.Профессия Backend-разработчик на Go | Skillfactory

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

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: 203 400 руб.

  • Длительность: 12 месяцев

  • Формат обучения: текстовые и видеоматериалы, вебинары, домашние задания, тесты, тренажеры

  • Сертификат: сертификат или диплом о профессиональной переподготовке

Преимущества курса:

  • подготовка к трудоустройству;

  • много практических заданий;

  • ответы на любые вопросы;

  • групповые проекты;

  • помощь в трудоустройстве в зарубежную компанию;

  • обучение прохождению интервью с HR-менеджерами и рекрутерами.

Недостатки курса:

  • нет доступа к базе знаний по окончании курсов;

  • недостаточная обратная связь.

Программа обучения:

  • Программирование на Go.

  • Структуры данных и алгоритмы.

  • Основа многопоточности.

  • Работа с базами данных.

  • Инструменты.

  • Продвинутое изучение.

  • Основы и архитектура DevOps.

Ознакомиться с полной программой курса >>>

5. Golang Developer. Basic| OTUS.ru

Онлайн-курс предусматривает обучение Golang с нуля. Он достаточно простой и уже много лет подряд занимает лидирующие позиции среди разработчиков. Язык поможет быстро разрабатывать архитектуру веб-сервисов и приложений, чтобы не тратить время на мониторинг устаревших синтаксических конструкций. Он прост в освоении и исключает рутинные операции, так как они возложены на встроенные инструменты. Курс будет полезен выпускникам технических вузов и тем, кто уже знает другие языки программирования.

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: 60 000 руб.

  • Длительность: 5 месяцев

  • Формат обучения: вебинары, видео, домашнее задание, проектная работа

  • Сертификат: да

Преимущества курса:

  • возможность корпоративного обучения;

  • полный комплект презентаций и видеозаписей всех вебинаров;

  • пополнение портфолио;

  • подойдет людям без опыта в программировании;

  • открытые уроки;

  • спикеры с большим практическим опытом.

Недостатки курса:

  • нет пожизненного доступа к материалам;

  • продолжительность вебинара.

Программа обучения:

  • Введение в Go.

  • Синтаксис и основы Computer Science.

  • Структуры и алгоритмы данных.

  • Основы Concurrency.

  • Решение типовых задач.

  • Особенности промышленной разработки.

  • Подготовка проекта.

Ознакомиться с полной программой курса >>>

6.Курс Разработчик Golang. Professional| OTUS.ru

Онлайн-курс познакомит с основами и внутренним устройством языка программирования. Он подойдет для бэкенд- и fullStack-разработчиков, DevOps-разработчиков, а также для тех, кто уже разобрался в основах языка и хочет прокачать свои скиллы для продвижения по карьерной лестнице. Программа разработана для быстрого углубления в Go и подойдет для тех, кто уже имеет опыт разработки в других языках.

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: 105 000 руб.

  • Длительность: 5 месяцев

  • Формат обучения: видеоуроки, вебинары, практические задания, выпускной проект

  • Сертификат: да

Преимущества курса:

  • вступительное тестирование для понимания уровня знаний;

  • корпоративное обучение;

  • работа в группах;

  • полный комплект обучающих материалов;

  • обучение на коммерческих задачах;

  • получение актуальных кейсов;

  • много проектов для портфолио.

Недостатки курса:

  • необходимы базовые знания и навыки;

  • желателен, но не обязателен опыт администрирования Линукс.

Программа обучения:

  • Знакомство с Go.

  • Стандартные практики и библиотеки.

  • Работа с БД и сетью.

  • Проект.

  • Микросервисы.

Ознакомиться с полной программой курса >>>

7.Golang для инженеров| Слёрм

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

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: от 50 000 руб.

  • Длительность: 8 недель

  • Формат обучения: видеоуроки, вебинары, вопросы спикерам, закрытый чат со студентами, практика

  • Сертификат: да

Преимущества курса:

  • доступ к постоянно обновляющимся материалам на два года;

  • видеоуроки доступны сразу же после оплаты;

  • обучение от спикеров с 10-летним опытом в сфере программирования;

  • пополнение портфолио;

  • корпоративное обучение и скидки;

  • много практики для закрепления навыков;

  • возможность повышения ценности на рынке труда.

Недостатки курса:

  • необходимы базовые знания и навыки;

  • чем дешевле курс, тем меньше информации в нем.

Программа обучения:

  • Основы Golang.

  • Погружение в основы языка программирования.

  • Конкурентность.

  • Библиотеки и сложные программы.

  • Работа с API.

  • Паттерны и операторы Kubernetes.

Ознакомиться с полной программой курса >>>

8. Изучение языка Golang| itProger

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

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: по запросу

  • Длительность: 9 уроков и 29 заданий

  • Формат обучения: видеоуроки, практика

  • Сертификат: да

Преимущества курса:

  • получение знаний в перспективной профессии;

  • в течение курса вы сможете построить небольшой сайт;

  • работа в программе Atom;

  • знакомство с исходным кодом;

  • к каждому уроку предусмотрено практическое занятие;

  • возможность тестирования на знание языка программирования, который подходит именно вам.

Недостатки курса:

  • отсутствие доступа к материалам после обучения;

  • рекомендуется иметь навыки в CSS и HTML.

Программа обучения:

  • Введение в язык программирования.

  • Отслеживание адресов сайтов.

  • Создание моделей данных.

  • Работа с шаблонами HTML.

  • Подключение MySQL.

  • Настройки новостного сайта.

  • Добавление данных.

  • Динамические страницы.

  • Публикация проекта на сервер.

Ознакомиться с полной программой курса >>>

9.Очный курс Go-разработчик| Бруноям

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

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: 66 500 руб.

  • Длительность: 3 месяца

  • Формат обучения: вебинары, воркшопы, видеоматериалы, практика

  • Сертификат: да

Преимущества курса:

  • быстрое обучение без потери качества;

  • помощь менторов на каждом этапе;

  • много практики в рамках домашних заданий;

  • возможность обучения от юрлица;

  • возврат оплаты в течение месяца, если курс не понравился.

Недостатки курса:

  • отсутствие доступа к обучающим материалам после окончания обучения;

  • несвоевременные ответы на вопросы от экспертов.

Программа обучения:

  • Основы языка.

  • Знакомство с Rest API.

  • Git.

  • Работа с БД.

  • Основы многопоточности.

  • Архитектура приложения.

  • Подготовка финального проекта.

Ознакомиться с полной программой курса >>>

10. Чистая архитектура приложения на GO| Слёрм

Онлайн-курс проходит в интенсивном формате в течение двух дней. Обучение в виде вебинара через Zoom ведется с 10 до 19 часов по московскому времени. Эксперт погружает в теорию и на практике показывает, как правильно работать с инструментами. После этого ученики приступают к выполнению заданий и могут задавать вопросы. Процесс обучения построен таким образом, что при получении большого объема информации, она структурируется и раскладывается по полочкам.

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: 20 000 руб.

  • Длительность: 2 дня

  • Формат обучения: вебинары, практика на стендах

  • Сертификат: да

Преимущества курса:

  • доступ к интенсиву на два года;

  • обратная связь от спикера в закрытом чате;

  • корпоративное обучение и скидки;

  • интенсивное изучение информации;

  • если пропустили вебинар, можно посмотреть его в записи.

Недостатки курса:

  • слишком большой объем информации в сжатые сроки;

  • длительный ответ от спикера, так как учеников слишком много.

Программа обучения:

  • Создание структуры проекта.

  • Разработка структуры папок в чистой архитектуре.

  • Бизнес логика в Domain.

  • Создание интерфейса для Repository и UseCase.

  • Работа с конструкторами слоев.

  • Использование контекста.

  • Работа с логированием ошибок.

Ознакомиться с полной программой курса >>>

11. Онлайн-практикум Golang-разработчик. Advanced| Rebrain

Golang-обучение на онлайн-курсе поможет вам быстро разобраться в простом инструменте, который позволяет создавать сетевые приложения, системы мониторинга, консольные утилиты и пр. Программа позволяет понять концепцию микросервисного взаимодействия, настраивать его работу с окружением, а также собирать метрики. Если вы DevOps-инженер, то сможете расширить свой кругозор в плане современного подхода к автоматизированной разработке.

ТОП-15 курсов для Golang-разработчиков и бесплатное обучение программированию на языке GO Обучение, Образование, Разработка, Развитие, IT, Golang, Длиннопост, YouTube (ссылка), Блоги компаний
  • Стоимость: 45 000 руб.

  • Длительность: 3 месяца

  • Формат обучения: видео, практика, вебинары

  • Сертификат: да

Преимущества курса:

  • все задания идут в портфолио;

  • 90% практики;

  • все работы проверяет эксперт;

  • проверка домашних работ в течение 24 часов;

  • живые мастер-классы;

  • чат с экспертами и педагогами;

  • помощь в составлении резюме.

Недостатки курса:

  • отсутствие доступа к обучающим материалам после обучения;

  • растянутый процесс обучения.

Программа обучения:

  • Работа с БД.

  • Создание сервера.

  • Низкоуровневость.

  • Микросервисная архитектура.

  • Межсервисное взаимодействие.

  • Оптимизация.

  • Работа в кластере.

Ознакомиться с полной программой курса >>>

Бесплатные курсы по Golang

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

1. Курс Go: онлайн обучение с нуля, бесплатно — Code Basics

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

Основные характеристики курса:

  • много практических заданий для оттачивания новых навыков;

  • знакомство с базовыми конструкциями языка;

  • особенности каждого типа коллекций;

  • обучение в свободном темпе;

  • возможность задавать вопросы экспертам.

2. Бесплатный курс «Основы Go» — Яндекс Практикум

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

Основные характеристики курса:

  • обучение на рабочих задачах и реальных кодах;

  • теорию можно изучать в свободном темпе;

  • практика выполняется в специальном редакторе кода;

  • на каждом этапе можно обратиться за помощью к куратору;

  • доступ в сообщество студентов.

3. Программирование на Golang — Stepik

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

Основные характеристики курса:

  • основы goland;

  • предоставление сертификата по окончании обучения;

  • поддержка экспертов на этапе обучения;

  • итоговое тестирование;

  • подойдет для тех, кому интересен язык.

4. GOLANG РАЗРАБОТЧИК - CloudMTS

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

Основные характеристики курса:

  • после каждого блока обучения предусмотрена практика;

  • возможность совмещения работы и учебы;

  • подойдет только для студентов с опытом;

  • возможность стать частью команды CloudMTS;

  • обучение работе с брокерами сообщений и базами данных.

5. Изучаем Golang — ThisIsIT

Это небольшой канал на Ютьюбе, посвященный самостоятельному и бесплатному обучению Golang. 28 уроков познакомят не только с теорией, но и помогут на практике разобраться в тонкостях функций и инструментов, которые доступны для автоматизации разработки.

Основные характеристики курса:

  • обучение в свободном темпе в любое удобное время;

  • только актуальная информация, так как каналу всего лишь год;

  • не требуются базовые навыки и знания;

  • нет обратной связи от эксперта.

Заключение

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

Больше курсов программирования для Golang-разработчиков смотрите в нашем каталоге.

Показать полностью 12
Обучение Образование Разработка Развитие IT Golang Длиннопост YouTube (ссылка) Блоги компаний

Попробовать мобильный офис

Перейти
Партнёрский материал Реклама
specials
specials

Мобильный офис до 100 тысяч рублей⁠⁠

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

Протестировали TECNO MEGABOOK K15S вместе со смартфоном TECNO CAMON 40 и наушниками TECNO в рабочих и бытовых сценариях от Zoom-звонков до перелета, а теперь рассказываем, как себя показала техника.

Первое впечатление от дизайна ноутбука

Первое, что заметно — это вес. При диагонали 15,6 дюйма и полностью металлическом корпусе K15S весит всего 1,7 кг. Это примерно на 15% меньше, чем аналоги. Устройство не обременяет ни в офисе, ни в такси. Ноутбук поместился в стандартный городской рюкзак, было удобно достать его в кафе за завтраком и по дороге в такси, чтобы быстро отработать клиентские правки.

1/4

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

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

Также отметим 9 портов: USB-A, USB-C, HDMI, слот для карты памяти — можно забыть о переходниках.

В TECNO MEGABOOK K15S предустановлен Windows 11. Ноутбук готов к работе сразу после включения. Никаких лишних установок и обновлений. Все настроено и оптимизировано для вашей многозадачности.

Экран: яркая картинка и комфорт ночью

Экран — 15,6 дюйма, IPS-матрица с разрешением Full HD. Углы обзора отличные: изображение остается четким, даже если смотреть сбоку, цвета не искажаются. Есть антибликовое покрытие. Тестировали ноутбук при разном освещении: можно спокойно работать у окна. Когда солнце бьет прямо в экран, текст по-прежнему остается читаемым, картинки не искажаются. Это редкость в бюджетных моделях.

1/2

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

Стеклокерамический крупный тачпад — 15 см. Он не залипает, не промахивается, срабатывает с первого касания. Не возникает дискомфорта, даже если несколько часов редактировать документы без мышки. После перехода с других устройств немного непривычно, что тачпад работает в двух направлениях: нижняя часть отзывается нажатием, верхняя — касанием.

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

Производительность: рендерим видео, открываем вкладки

Ноутбук работает на AMD Ryzen 7 5825U (опционально можно выбрать версию техники Intel Core i5-13420H). Восьмиядерный AMD с поддержкой 16 потоков подходит для ресурсоемких операций вроде рендеринга или работы с большими массивами данных. Встроенная графика Radeon справляется с редактированием видео в Full HD или играми.

1/4

Во время монтажа 30-минутного ролика в DaVinci Resolve и параллельной работе в Photoshop с несколькими большими PSD-файлами система сохраняла стабильность. Не было ни зависаний, ни заметного падения производительности. Ноутбук уверенно держит в фоне 10 приложений одновременно. Если запущены браузер с 20 вкладками, видеозвонок в Telegram, Excel с объемной таблицей и софт для монтажа, система не тормозит и не перегревается. Переход между окнами остается плавным, ничего не «проседает», даже при одновременном скачивании файлов и редактировании видео.

Базовая комплектация включает 16 ГБ оперативной памяти в двух слотах. При необходимости можно легко увеличить этот показатель до 32 ГБ, заменив стандартные модули на более емкие. Помимо установленного SSD на 1 ТБ предусмотрен дополнительный слот, поддерживающий диски объемом до 2 ТБ.

Чтобы во время нагрузки системы охлаждения не выходили из строя, в ноутбук встроен эффективный вентилятор, способный рассеивать до 35 Вт тепла. Устройство не греется, его спокойно можно держать на коленях. Это решение дополнено тремя режимами работы, которые переключаются простой комбинацией клавиш Ctrl+Alt+T. Тихий режим идеален для работы ночью или в общественных местах, сбалансированный подходит для повседневных задач. Производительный, на котором запускали рендеринг видео и игры, практически не шумит.

Автономность: 15 часов без подзарядки

Протестили автономность MEGABOOK K15S в условиях, знакомых каждому деловому путешественнику. Утром перед вылетом зарядили ноутбук до 100% и взяли его в рейс Москва — Калининград. В зале ожидания провели созвон, потом три часа смотрели сериал и в дороге до отеля редактировали документы. К моменту приезда оставалось 40% заряда: хватило бы еще на пару часов продуктивной работы.

1/3

MEGABOOK K15S может автономно работать до 15 часов и позволяет не оглядываться на индикатор заряда. Заявленное время достигается при типичном офисном использовании: одновременная работа с документами в Word и Excel, ведение переписки, видеоконференции, веб-серфинг.

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

Звук, который реально слышно

В TECNO MEGABOOK K15S установлены два мощных динамика по 2.5 Вт. Звук с глубокими низами, без пластикового дребезжания, объемный. Благодаря DTS можно смотреть видео даже в шумном помещении. В тестах специально включали сцены с шагами и выстрелами: локализация настолько точная, что в наушниках нет необходимости.

Та же стабильность и в микрофоне. Благодаря AI-шумоподавлению голос передается чисто. Во время тестовых звонков из оживленного кафе собеседник не услышал ни разговоры за соседним столом, ни городской шум. И все это — на расстоянии до пяти метров.

Кстати, о созвонах. В ноутбуке встроена обновленная камера. Она отслеживает положение лица, а еще есть физическая шторка приватности. Например, можно закрыть шторку для комфортных видеоконференций.

Для тех, кто предпочитает гарнитуру, идеально подойдут беспроводные наушники TECNO FreeHear 1 из экосистемы бренда. Когда не хотелось делиться разговорами с окружающими, подключали их. Чистый звук с акцентом на средние частоты, 11-мм драйверы, которые выдают неожиданную детализацию. Музыку слушать приятно: и фоновый плейлист на телефоне, и вечерний сериал на ноутбуке. Автономно работают наушники 6 часов, с кейсом — до 30 часов. 

1/2

Bluetooth 5.4 обеспечивает стабильное соединение на расстоянии до 10 метров. Удобная C-образная форма разработана специально для длительного ношения — после восьмичасового рабочего дня в ушах не возникает дискомфорта. Наушники поддерживают одновременное подключение к ноутбуку и смартфону. Переключение между устройствами происходит быстро и без заминок.

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

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

Бесшовная синхронизация со смартфоном

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

Функция выручила, когда нужно было открыть приложение, у которого нет веб-версии. Удобно работает и буфер обмена: скопировал текст на одном устройстве — вставил на другом. Например, код, полученный в сообщении на телефоне, вводится в браузере на ноутбуке. Экономит минуты, а иногда и нервы. А когда в дороге пропал Wi-Fi, ноутбук сам подключился к мобильному интернету через смартфон.

1/2

TECNO CAMON 40 и сам по себе — мощный рабочий инструмент.  Смартфон выделяется камерой высокого качества 50 Мп, ярким AMOLED-экраном 120 Гц и множеством функций, которые упрощают процесс мобильной съёмки и использование искусственного интеллекта TECNO AI.

Телефон работает на HIOS 15.0.1 на базе Android 15.В фирменную оболочку встроен искусственный интеллект:

  • Голосовой помощник Ella. Отвечает на вопросы, помогает с задачами и управлением устройством.

  • Решение задач. Наводите камеру на задачу, ИИ решает ее.

  • AI Редактор фотографий. Интеллектуальная обработка в одно касание.

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

Технические характеристики

  • Процессор и память. 8 ядер, 16 потоков, Кэш L3 16 МБ, частота до 4.5 ГГц Графический процессор AMD Radeon™ graphics SSD 512 ГБ или 1 ТБ, М.2, 2280, PCle 3.0 Nvme DDR4 16 ГБ, 3200 МГц.

  • Дисплей. 15.6", TFT, Full HD (1920×1080), 16:9, 280нит, 45% NTSC, 16.7 млн цветов, 60 Гц, 141 ррі.

  • Веб-камера. 1 Мп, шторка приватности.

  • Порты. 9 портов: 1*TF Card (microSD), 1*HDMI 1.4, 1*USB-A 3.1,

    1*USB-A 3.2, 1*3.5mm аудиовход, *Ethernet RJ45 до 1 Гбит, 2*Туре-С (Full Function), 1*слот для замка Kensington.

  • Другое. Сканер отпечатка пальца в кнопке питания. Клавиатура с подсветкой (4 уровня яркости). Тачпад с поддержкой одновременно 4 касаний.

  • Батарея. 70 Вт∙ч (6150 мА∙ч), Li-Pol, 11.55 B 65 Вт Type-C GaN, 20 В, 3.25 А, кабель 1.8 м (Туре-С-Type-C).

  • Габариты. 17.3 мм (высота), 359.5 мм (ширина), 236 мм (глубина).

  • Вес. 1,7 кг.


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

КУПИТЬ НОУТБУК TECNO

Реклама TECNO Mobile Limited, Юридический адрес: Flat N, 16/F., Block B, Универсальный промышленный центр, 19-25 Shan MeiStreet, Fotan, New Territories, Гонконг

Показать полностью 17
Электроника Гаджеты Ноутбук Длиннопост
NutrientElement
NutrientElement
1 год назад
Типичный программист
Серия Программирование

Под капотом каналов в golang⁠⁠

Внутренняя реализация каналов в Go основана на механизме синхронизации и передачи данных между горутинами.

Под капотом каналов в golang Программирование, IT, Программист, Golang, Разработчики, Разработка

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

Внутренняя реализация каналов в Go включает в себя следующие компоненты:

  • Структура channel: Когда вы создаете канал в Go, создается структура channel, которая содержит информацию о типе данных, буфере (если он есть) и других метаданных канала.

  • Буфер: Каналы могут иметь опциональный буфер, который позволяет хранить определенное количество элементов перед тем, как горутина будет заблокирована при попытке отправки данных в полностью заполненный канал или получении данных из пустого канала. Буфер реализован с помощью внутренней очереди FIFO (First-In-First-Out).

  • Мьютексы: Для обеспечения безопасности доступа к данным в канале используются мьютексы (mutexes). Мьютексы блокируют доступ к данным, пока другая горутина не освободит их. Это позволяет предотвратить состояние гонки (race condition) при одновременной записи и чтении данных из канала.

  • Указатели на горутины: Каналы хранят указатели на горутины, которые ожидают отправки или получения данных. Когда горутина отправляет данные в канал или получает данные из канала, она блокируется, пока другая горутина не освободит канал.

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

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

Интересные факты и фичи языков программирования у нас в канале, заходи :)

Показать полностью
[моё] Программирование IT Программист Golang Разработчики Разработка
0
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии