-Поиск по дневнику

Поиск сообщений в rss_rss_hh_full

 -Подписка по e-mail

 

 -Постоянные читатели

 -Статистика

Статистика LiveInternet.ru: показано количество хитов и посетителей
Создан: 17.03.2011
Записей:
Комментариев:
Написано: 1

Habrahabr








Добавить любой RSS - источник (включая журнал LiveJournal) в свою ленту друзей вы можете на странице синдикации.

Исходная информация - http://habrahabr.ru/rss/.
Данный дневник сформирован из открытого RSS-источника по адресу http://feeds.feedburner.com/xtmb/hh-full, и дополняется в соответствии с дополнением данного источника. Он может не соответствовать содержимому оригинальной страницы. Трансляция создана автоматически по запросу читателей этой RSS ленты.
По всем вопросам о работе данного сервиса обращаться со страницы контактной информации.

[Обновить трансляцию]

Дайджест интересных материалов для мобильного разработчика #223 (25 сентября — 1 октября)

Воскресенье, 01 Октября 2017 г. 16:16 + в цитатник
EverydayTools сегодня в 16:16 Разработка

Дайджест интересных материалов для мобильного разработчика #223 (25 сентября — 1 октября)

    Подводим итоги очередной недели мобильным дайджестом. В нем мы рассказываем про разработку прибыльной игры школьниками, про iOS-релизы в Badoo, про новые правила App Store и победителей Google Play, иллюзии скорости и движения, анонимность и многое другое.



    Разработка прибыльной Android игры двумя школьниками + Продолжение

    В данной статье хочу рассказать вам об опыте разработки одной простенькой игры под Android, которая многократно окупилась еще на стадии разработки!

    Процесс релиза iOS-приложений в Badoo

    Меня зовут Михаил Булгаков, и я работаю в команде релиз-инженеров Badoo. В этом посте я расскажу о том, как происходят релизы iOS-приложений с момента «У меня есть готовый бинарь» до момента «После нас хоть потоп», и, конечно, как это делаем мы в Badoo.

    Как работает Android, часть 3

    В этой статье я расскажу о компонентах, из которых состоят приложения под Android, и об идеях, которые стоят за этой архитектурой.

    Дайджест доступен и в виде рассылки. Подписаться вы можете тут (у нас уже 2000+ подписчиков!).

    iOS

    (+24) Больше сюрпризов от Apple: обновленные правила размещения на App Store
    (+13) iOS+Kotlin. Что можно сделать сейчас
    (+8) Опционалы в Swift
    Podlodka #26: реактивный стиль программирования
    Stack AR: первая игра на основе ARKit, возглавившая топ App Store
    Полный разбор дизайна iOS 11: Apple все еще внимательны к деталям?
    image Первое React Native приложение: от «Hello World» до App Store
    image Отладка Swift с LLDB
    image Как уйти из колледжа и стать iOS-фрилансером
    image Управление разными средами в Swift-проекте
    image Руководство по ARKit для новичков
    image Чистая Swift архитектура
    image В Xcode 9 цвета можно добавлять в каталог ассетов
    image Измерение времени компиляции в Xcode 9
    image React Native Game Center: интеграция Game Center в React Native
    image ButtonProgressBar: прогресс бар в кнопке
    image Detect.Location: история посещения мест по фотографиям
    image LifetimeTracker: отслеживание ключевых проблем прямо во время разработки

    Android

    (+11) Делаем MitM с помощью openssl на Android
    (+11) Библиотека Reamp: обезболивающее для ваших Android-приложений
    (+11) Реактивные приложения с Model-View-Intent. Часть 2: View и Intent
    (+8) 30 новых ресурсов для android-разработчика (лето 2017)
    (+4) CSV-библиотека Adaptive Table Layout
    Лучшие приложения Google Play за пять лет
    image Android Dev Подкаст. Выпуск 43. Обзор Devfest Siberia 2017
    Победители Google Play Indie Games Festival
    Создание макета в ConstraintLayout: нормативы, барьеры и цепочки
    В Android O изменился файл хранения паролей от от wi-fi сетей
    Как парсить XML на Android
    image RxJava: делаем креш-логи лучше
    image Многопотоковый рендеринг на Android с Litho и Infer
    image Flutter: от дизайна до приложения
    image Использование шрифтов с Support Library 26
    image Android Architecture Components: тестирование ViewModel LiveData
    image Наслаждение тулбаром
    image Воссоздаем “Бутылочку” на Android
    image Используем buildSrc для кастомной логики сборок Gradle
    image Как улучшить быстродействие Android Studio на машине с малым объемом памяти
    image Frames: готовое приложение с обоями
    image Tutorial View: простая организация туториалов
    image Croller: круглый контрол

    Разработка

    (+89) Иллюзия движения
    (+72) Иллюзия скорости
    (+21) Как мы за неделю создали чат-бота и подружили его с веб-приложением
    (+19) Learnopengl. Урок 3.3 — Класс 3D-модели
    (+15) Oblique frustum. Внутри скошенной пирамиды видимости
    (+11) Зачем в 2017 году писать свой движок для мобильных игр?
    (+10) Как Алексей Моисеенков дошел до Prisma и пошел дальше
    (+9) Как довести первый проект до конца. Часть 2. Мифы, ошибки и провалы
    (+8) «Нормальный у нас такой UX. UX? Не до этого нам, у нас тут сроки поджимают!» Снимаем мантию — моя интерпретация
    (+6) Как сделать gif-анимацию для Behance и Dribbble?
    Почему WebAssembly значительно изменит веб
    Как обучаются и растут junior-разработчики в BBC
    Inkdrop: как я создал редактор, зарабатывающий $1300 в месяц
    Jovo: open source фреймворк для разработки кроссплатформенных голосовых приложений
    “А что, так можно было?”: Рейтинг разработчиков будет пересмотрен
    Как tbh превратило анонимность во благо
    Мобильное Облако Mail.Ru внедрило технологии компьютерного зрения
    image Mission-driven интерфейс
    image Мобильная типографика
    image Как получить работу в продуктовом или UX дизайне без портфолио
    image Вопросы и ответы по Code Review
    image Лучший кодинг через тестирование
    image Понимаем Progressive Web App: стоят ли они всей шумихи?
    image Как неинтуитивный пользовательский интерфейс может создать превосходный пользовательский опыт
    image 19 альтернатив Parse в 2017 году

    Аналитика, маркетинг и монетизация

    (+4) Мобильные приложения: что такое предпраздничный сезон-2017 и как заработать на нем максимум?
    Игры жанра match3: как разработать такую игру и сделать её лучше
    Tune проводит увольнения
    Топ рекламных платформ для привлечения установок
    Фрод со сбросом DeviceID: новая угроза в мобильном маркетинге
    image Три стадии мобильного маркетинга
    image Аналитика против атрибуции — Работа с несоответствием установок

    Устройства, IoT, AI

    (+20) Тайм-менеджмент для кинестетиков
    «Путь будущего»: бывший главный инженер Uber создал религию ИИ
    LG представила смартфон с отпугивателем комаров
    Amazon выпускает новые колонки и умные часы
    Какие языки вам стоит изучить для Data Science?
    image Microsoft запускает новые инструменты машинного обучения

    <- Предыдущий дайджест. Если у вас есть другие интересные материалы или вы нашли ошибку — пришлите, пожалуйста, в почту.
    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/339082/


    Метки:  

    [Из песочницы] Как легализовать торговлю игровыми предметами

    Воскресенье, 01 Октября 2017 г. 15:11 + в цитатник
    Hyperevolution сегодня в 15:11 Маркетинг

    Как легализовать торговлю игровыми предметами

    image

    Объем российского рынка онлайн-игр по итогам 2016 года составил 56,7 млрд руб. (по данным Mail.Ru Group), общемировой объем рынка онлайн-игр в 2016 году — $99,6 млрд (по данным Newzoo), но только 6% пользователей умеют зарабатывать на внутриигровых предметах. Игровые пространства предлагают активно покупать амуницию, камуфляж, прогресс персонажа, но легально продать кому-то свою коллекцию ты не можешь, как не можешь и вывести деньги из игры, инвестировав время, скилы и удачу.

    Имея большой опыт в игровой индустрии (Suntechsoft, Esforce, Na’Vi’ и др.), мы придумали, как объединить все игры и платформы и дать геймерам возможность в один клик продавать, обменивать или оценивать виртуальные предметы. Сервис DMarket будет работать на базе блокчейн, а все операции внутри маркетплейса можно будет осуществлять с помощью встроенных токенов и умных контрактов.

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

    От виртуального — к реальному


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

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

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

    Рассмотрим крупнейших игроков на глобальном рынке внутриигровых предметов.

    Steam


    Ежедневное количество активных пользователей: 12 853 536 (по состоянию на 15.07.2017);
    Количество игр: + — 14 398 (по состоянию на 15.07.2017).

    image

    Платформа Steam была выпущена в 2003 году. За последние 4 года она завоевала огромную популярность среди игрового сообщества, прибыль в 2016 — $3,5 млрд. Steam первым обратил внимание на торговлю внутриигровыми предметами. Правда, вся полученная прибыль удерживается внутри платформы, возможности обналичить деньги нет. Более того, возможность торговать игровыми предметами ограничена и представлена всего в нескольких играх (CS:GO, Dota2, TF2, PUBG, H1Z1).

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

    • крупнейший рынок для продажи видеоигр и модов;
    • темп продаж увеличивается, и каталог игр стремительно расширяется. На сегодняшний день активировано почти 370 млн платных игр;
    • Steam предлагает дополнительные сервисы для игроков, моддеров и разработчиков игр: торговля предметами, бета/альфа релизы, предварительная продажа игр, реестр предметов, обработка платежей и проверка кредитных карт.

    Недостатки Steam:

    • технологии и серверы Steam централизованы и имеют полный контроль над доступностью каждого отдельного товара или элемента в своем каталоге. Это приводит к мошенничеству в сфере безопасности (учетной записи);
    • большинство игр в Steam не поддерживают внутриигровую торговлю. Только три игры оказывают значительное влияние на общий оборот внутриигровых предметов (CS:GO, Dota2, TF2);
    • пользователи Steam не имеют реального влияния на развитие платформы;
    • Steam не позволяет своим пользователям обналичивать виртуальную валюту платформы;
    • Steam взимает высокую комиссию за торговлю игровыми предметами (до 12%);
    • Steam не поддерживает мультиплатформенную торговлю и торговлю на разных игровых движках.

    Opskins


    Opskins – это площадка для торговли внутриигровыми предметами, которая была запущена в 2014 году. Opskins сохраняет безопасность как покупателей, так и продавцов, выступая в качестве сторонней платформы. Деньги можно вывести на счет PayPal, банковский счет, биткойн-кошелек, карту предоплаты Visa и т.д.

    image

    Сервис применяет API Steam, позволяющий торговать внутриигровыми предметами. На данный момент Opskins является крупнейшей в мире платформой для торговли скинами с 10 млн уникальных пользователей в месяц.

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

    • оборот за І и ІІ кварталы 2017 года составил около $250 млн;
    • одно из самых крупных сообществ по продаже скинов (более 10 млн пользователей каждый месяц);
    • обналичивание реальных денег.

    Недостатки Opskins:

    • не имеет официальной поддержки Steam (большое количество случаев мошенничества с аккаунтами);
    • высокая комиссия за транзакции и вывод средств (до 10%);
    • поддерживает всего несколько игр Steam;
    • в большой степени зависит от Steam из-за использования API-интерфейса этого сервиса.

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

    В начале статьи мы говорили о 2,15 млрд геймеров. Именно такое количество людей во всем мире играет в игры на разных платформах. Если бы все они получили возможность торговать своими виртуальными раритетами, ежегодный оборот игрового контента в денежном выражении превысил бы $450 млрд.

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

    Второй важный момент — интерес разработчиков и издателей игр. Мы не уводим пользователей от покупки непосредственно внутри игр в сторону покупок у частных лиц, мы создаем сообщество, в котором продажа и обмен предметов будет только частью процесса. Благодаря блокчейн, будет сохраняться история каждого виртуального артефакта, можно будет проследить, кто владел раньше условным автоматом, кто был первым покупателем, где он использовался. Это создает историю каждой вещи, и из безликого инструмента для достижения игровых целей она превращается в предмет коллекционирования. Пользователи будут продавать одни предметы и покупать другие, а потом возвращаться в игру, чтобы использовать полученные возможности. Таким образом увеличится время, которое игрок проводит внутри игры, жизнь каждого предмета и жизненный цикл самой игры.
    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/339074/


    Метки:  

    [Из песочницы] Информационная безопасность в АСУ ТП: вектор атаки преобразователи интерфейсов

    Воскресенье, 01 Октября 2017 г. 13:29 + в цитатник
    2younda сегодня в 13:29 Разное

    Информационная безопасность в АСУ ТП: вектор атаки преобразователи интерфейсов

    Размышление


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

    Выступал там один парень с докладом об ИБ в АСУ ТП, рассказывал о том, что на протяжении длительного времени эволюция систем автоматизации шла параллельным курсом с развитием ИТ систем и что с течением времени для управления системами автоматизации стали применяться системы, построенные на современных ИТ технологиях. И что в настоящее время сопряжение технологической сети с корпоративной сетью необходимо для управления производством так и для администрирования всей системы целиком. Вектор атак с систем ИТ перешел на производственные и промышленные сети. Рассказывал о заводе где-то в германии на который удалось произвести атаку и сорвать технологический процесс в результате чего литейное производство встало и понесло огромные убытки, а литейный цех пришлось разбирать и еще много страшных историй. Ну в общем доклад не произвел нужного(пугающего) впечатления. Присутствующие на данном мероприятии начали задавать вопросы и обсуждать," мол кому мы нужны маленькие компании с минимальными оборотами денег, что мол есть ли реальные подтверждения инцидентов с атаками на предприятия у нас в России".

    Парень не смог привести примеры: либо не был готов, либо не имел право разглашать ту информацию которой он владел. Так к чему этот рассказ?

    После данного мероприятия я задумался почему люди так отреагировали на его выступления, ведь он хорошо оперировал терминами и международной статистикой по атакам на объекты, но люди посчитали что эти атаки маловероятны и не представляют угрозы для них. Именно это побудило меня заняться исследованием в области информационной безопасности АСУ ТП.

    Немного теории


    Рассмотрим нетипичное направление атаки на преобразователи интерфейсов, т.к. много информации об атаках на ПК, ПЛК и системы в целом, но мало кто задумывался что почти на каждом производстве имеются все различные системы устройств, датчиков, приборов и есть проблема совместимости различных видов устройств. Существует огромное разнообразие устройств различного вида и назначения, большое количество компаний, занимающихся их производством, разные стандарты, большей частью не совместимые между собой. Выходом из этой ситуации служат преобразователи интерфейсов. Все они применяются для подключения устройств с интерфейсом RS-232/422/485, а это системы сбора данных, регистраторов, контроллеров, датчиков, терминалов и многого другого. Но мало просто соединить порты необходимо установить связь на программном уровне, что является более сложной задачей. Разные стандарты устройств способны передавать данные по различным технологиям. Унифицировать протоколы привести передаваемые данные к единому виду с помощью преобразователей не получиться, но адаптировать вид данных передаваемых между различными частями системы различными протоколами, чтобы они были успешно приняты и расшифрованы элементом, использующий другой протокол возможно.

    А те, кто эксплуатирует реальные системы АСУ ТП знают насколько иногда разнообразно оборудование и части этой системы, которые в некоторых случаях работают на производстве уже порядка 10-15 лет и поверх одной системы приходиться иногда ставить другую систему и добиваться ее сращивание, что бы все взаимодействовало между собой. Вот тут преобразователи интерфейсов подходят как никогда. Преобразование пакетов, передаваемых данных происходит на программном уровне. Помимо непосредственно изменения структуры передаваемых данных, программная составляющая преобразователя отвечает за определение типов протоколов, используемых в системе и выбор алгоритма для их согласования.

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

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

    К практике


    Мы проведем эксперимент с очень популярными преобразователями тайваньской фирмы MOXA Nport различных версий. Пользоваться будем свободно распространяемым ПО и разрешенными ресурсами на уровни простых пользователей.

    Есть в сети такой очень интересный ресурс www.shodan.io позволяет найти устройства в глобальной сети интернет, к которым есть доступ и увидеть где они находятся. Выполним простое сканирование с вводом в поисковой строке Moxa Nport. Смотрим и удивляемся тому, что происходит в мире. Стоит учитывать, что некоторые организации направляют письменный запрет на сканирование их подсети в компанию www.shodan.io.

    В общем случаи мы нашли 7260 устройств по запросу Moxa Nport во всем мире. Дальше изучаем как можно попасть на устройства к которым открыт доступ. Замечаем, что в большинстве своем 22, 23, 80, 443 порты открыты и через них можно спокойно подключиться к устройствам.



    Тайвань



    Польша



    Липецк



    Китай



    Казань



    Тайвань



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



    Попадаем на устройство и смотрим все что нужно, убеждаемся, что есть права администратора.





    Можем как просмотреть всю информацию, так и изменить ее.



    Некоторые пользователь устанавливают нестандартные пароль и закрывают 80 порт, но www.shodan.io все равно есть возможность просмотра полезной информации и по другим портам которая может быть использована для развития вектора атаки. Название устройство, его статус, мак адреса, SSL certificate его версию и многое другое.



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



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



    Но это только начало, используем стандартные пары ( а таких устройств нашлось не мало и в России, Чехии, Польше, Италии, Австралии, и во многих других странах).



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









    И смена паролей и перезагрузка, в общем неограниченные права администратора.

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

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

    Проходим на ics-cert.us-cert.gov и в поисковике просто указываем интересующее нас оборудование и имеем официальный список признанных уязвимостей от компании MOXA и этот список разнообразный.



    Гуглем дальше и узнаем о том что эксплуатация уязвимостей позволяет атакующим незаметно выполнить различные действия на устройстве. Оборудование Тайваньской компании MOXA подвержено уязвимостям позволяющим удаленному неавторизованному пользователю получить доступ с правами администратора к устройствам и важной информации хранимой в незашифрованном виде. Так же злоумышленник может осуществить CSRF-атаку. Успешная эксплуатация данных уязвимостей позволяет атакующему незаметно выполнить различные команды, изменить пароль, настройки, и перезагрузить устройство.

    Появление проблем является следствием недостаточной защиты систем АСУ ТП в общем. К примеру преобразователи поставляются без установленного пароля или со стандартным заводским паролем и учетной записью (CVE-2016-2286). Как и многие устройства для систем АСУ, что позволяет любому пользователю получить доступ правами администратора к устройству через TCP/80(HTTP) и TCP/23(Telnet). В настоящее время как утверждает производитель нет информации о случаях активной эксплуатации ошибок. И производитель рекомендовал в свое время просто отключать порты TCP/80(HTTP) и TCP/23(Telnet).



    CVE-2016-0875 Позволяет удаленному пользователю повысить свои привилегии и получить доступ к конфигурационным и лог файлам с помощью специально сформулированного URL.

    CVE-2016-087 удаленный атакующий может вызвать отказ в обслуживании путем отправки специально сформулированного запроса.

    CVE-2016-0877 связана с PING функцией, а ее эксплуатация может привести к утечкам данных.

    CVE-20164500 затрагивает встраиваемые компьютеры uc7408 lx plus позволяет удаленному авторизированному пользователю перепрашивать устройства и вызывать отказ в работе.

    CVE-016-8717 эксперты обнаружили в устройствах MOXA жестко закодированные учетные данные которые позволяют войти в недокументированный аккаунт.



    Исследователи и различные специалисты регулярно находят помимо уязвимостей, багов, и устаревшего ПО, бэкдоры. О безопасности интернет вещей в целом говорят все больше, однако от таких крупных производителей коммуникационного оборудования, как компания MOXA подобного ни кто не ожидал. Ведь проблемы обнаружены в целом ряде случаев, начиная от проблем с аутификацией которая допускает проведение словарных атак, множества XSS багов в веб интерфейсе, DoS- уязвимостями, возможностью инъекции команд.

    Для большинства проблем производитель выпустил корректирующие обновления прошивок устраняющие ряд уязвимостей, в других случаях MOXA приняла решения прекратить выпуск некоторых устройств в связи с невозможностью, а иногда и не желанием устранять уязвимости.
    Узнав о таких уязвимостях от такого крупного производителя, всем кто использует оборудование данной компании надо бы задуматься об обновлении прошивок, смене паролей, и настроек устройства. Но в практике АСУ ТП все гораздо сложней. На производстве работает оборудование которое вообще ни когда не обновлялось, либо не может быть обновлено в связи с технологией непрерывного производства. И тут вопросов возникает еще больше, но это уже другая история и другой вектор атаки.

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

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

    Выводы


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

    — Нижний уровень- уровень датчиков и исполнительных механизмов
    — Средний уровень- уровень промышленных контроллеров
    — Верхний уровень- уровень промышленных серверов и сетевого оборудования
    — Операторский уровень –уровень оператора и диспетчерских станций

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


    Процент атакованных промышленных компьютеров по месяцам в России за 2016 год

    Мы с вам в данном исследовании убедились, что такие атаки реальны и могут касаться как обычных пользователей, которые используют преобразователи для удаленного подключения, управления и конфигурирования устройств по разным интерфейсам. Так и все различные организации сеть которых очень разнообразна и имеет различное оборудование функционирующее через преобразователи интерфейсов. Я на своем опыте имел дело как с преобразователями moxa для удаленного конфигурирования АТС так и для удаленного управления терминалами различных защит, которые передают и получают информацию из промышленной сети через преобразователи.

    Подход производителей промышленного ПО и оборудования к исправлению уязвимостей и ситуацию с устранением известных уязвимостей на предприятиях нельзя назвать обнадеживающим. Подавляющее большинство промышленных предприятий как малых так и больших, годами остаются уязвимы к атакам.Так какие выводы можно сделать: атаки нестандартного направления есть и будут.Защищаться от них надо и знать уязвимости тоже надо ибо информация это сила.Что касается преобразователей использующихся у меня на предприятии? Я проверил все оборудование MOXA, обновил все до последней версии, сменил и увеличил сложность паролей, изучил материалы про уязвимости данной фирмы и последовал рекомендациям экспертов, чтобы минимизировать шансы атакующих, если все таки атака будет иметь место.

    P.S. В результате данного исследования ни одно устройство не пострадало. И данный эксперимент преследовал исследовательские цели (показать реальность атак и их простоту).
    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/339066/


    Метки:  

    MobX — управление состоянием без боли. Лекция в Яндексе

    Воскресенье, 01 Октября 2017 г. 11:20 + в цитатник
    Leono сегодня в 11:20 Разработка

    MobX — управление состоянием без боли. Лекция в Яндексе

      Недостаток зависимостей в веб-приложении приводит к ошибкам в интерфейсе, избыток — снижает производительность. Руководитель отдела разработки интерфейсов Яндекса Азат razetdinov показывает, как библиотека MobX помогает отслеживать минимальный набор изменений и поддерживать консистентность состояния приложений, а также знакомит с инструментом mobx-state-tree, который позволяет совместить всё лучшее из MobX и Redux.




      — Меня зовут Азат Разетдинов, я представляю персональные сервисы Яндекса: Почту, Диск, Календарь, Паспорт, управление аккаунтом. Хотел бы рассказать про управление состоянием веб-приложения без боли.

      Что такое состояние приложения? Это центральное понятие в архитектуре всего веб-приложения. Там хранится все, от чего зависят остальные компоненты. Например, самое очевидное — отображение, представление состояния приложения в виде дом-дерева, которое вы видите в браузере.

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

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

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

      Как правило, состояние приложения — дерево, где очень много данных, есть какие-то списки, объекты, хэши, примитивные данные. Большая иерархичная структура.

      Проблема не в том, что она иерархичная, а в том, что она живая, она постоянно меняется. Меняется то в одном месте, то в другом. Какую проблему мы хотим решить?

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

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

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

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

      У этого подхода две проблемы.

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

      Но у этого подхода тоже есть проблема.

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

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

      В этом месте к нам на помощь приходит MobX. Он реализует подписку ровно на те поля состояния приложения, которые вы используете.

      Чтобы это показать, нужно объяснить, как это устроено изнутри.

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

      Давайте объявим такой класс — Person, человек. И объявим три поля, и пометим их декоратором observable. Имя, фамилия и кличка.

      Когда мы говорим про MobX, очень полезно проводить аналогию с Excel.

      Observable-поля — это просто исходные данные в ячейках.

      Они позволяют остальным концепциям следить за изменением себя.

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

      В данном случае мы просто конкатинируем имя и фамилию через пробел.

      Если проводить аналогию с Excel, это ячейка с формулой. Кажется, пока все просто.

      Этот не тот action, который вы, наверное, знаете из Redux, но он очень похож.

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

      Пока все понятно, метод устанавливает nickName.

      Теперь начинается магия.

      Самая главная концепция MobX — это реакции.

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

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

      Самая простая реакция — функция autorun из библиотеки MobX.

      Напишем простой autorun, в который передается функция, просто выводящая некое выражение в консоль.

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

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

      При выполнении этой функции он обращается к observable-полям, в данном случае первым делом к nickName. Здесь срабатывает магия MobX: на самом деле, когда мы объявляли observable, вместо обычного поля был объявлен getter для этого поля.

      Когда мы обращаемся, observable-поле nickName у себя ставит инкремент: ага, у меня появился новый слушатель функции, которая завернута в autorun.

      Когда у меня что-то изменится, мне нужно этого слушателя уведомить об этом изменении. NickName пустой, поэтому дальше идет обращение к Person fullName. У нас происходит подписка на изменение этого поля. FullName является computed-полем, это getter, который внутри себя обращается к полям firstName и lastName.

      На этом выполнение функции заканчивается, и в этот момент MobX знает, что функция, которую мы передали в autorun, зависит от четырех полей: nickName, fullName, firstName, lastName.

      Дерево зависимостей выглядит так. Любое изменение observable-полей в первом столбце запустит заново выполнение autorun.

      Допустим, мы решили задать нашему человечку кличку Васек.

      Этот метод, который является action, совершает внутри себя операцию присваивания.

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

      Autorun получает уведомление, что что-то изменилось, надо заново перезапуститься. Запускает выполнение функции, обращается к полю nickName.

      На сей раз оно уже не пустое. На этом выполнение функции прекращается.

      Смотрите, как изменился список наблюдаемых полей. Поскольку мы обращались только к полю nickName, он остается в списке наших зависимостей. Все остальные три поля из списка зависимостей тоже вылетают. Если посмотреть на дерево, оно теперь выглядит так.

      До тех пор, пока не изменится nickName, autorun вообще будет игнорировать любые изменения полей firstName и lastName, потому что код устроен таким образом, что пока nickName не пустой, до поля fullName дело даже не дойдет никогда.

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

      Autorun — не единственный пример реакции. Есть реакция observer. Это helper для React.

      Если наш пример переписать в виде React-компонента, он будет выглядеть примерно так.

      Мы используем декоратор observer. Напомню: можно использовать обычные обертки здесь. Внутри метода render мы обращаемся сначала к nickName. Если он пустой, тогда уже к fullName. Ровно та же логика. Единственное, при использовании observer мы не выполняем функцию autorun, а вместо этого он при любом изменении полей, на которые мы подписаны, запускает переадресовку вашего компонента.

      Автоматическая подписка компонентов плюс observer позволяет кардинально минимизировать количество перерисовок React-компонентов.

      Есть часто наблюдаемый код, когда имеется какой-то флаг, который мы проверяем в самом начале метода render. Если он не выполняется, мы просто возвращаем null. Здесь очень помогает магия React. До тех пор, пока изменения у нас false, изменения любых полей, которые используются ниже, где написано много кода, observer будет игнорировать. Но как только флаг загорится, во время очередного перерендера он выполнит очередной код и подпишется на изменения полей, которые там используются.

      Если React экономит нам операции с домом, то MobX экономит нам операции с виртуальным домом. Чем меньше перерисовок даже в виртуальном доме, тем быстрее наше приложение.

      Расскажу об еще одной оптимизации, которая встроена в MobX, — кэшировании computed.

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

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

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

      Кэширование всегда зависит от наличия подписчиков, которых всегда может быть больше, чем один.

      Небольшой пример того, как можно работать с асинхронными данными при таком подходе.

      Можно руками запускать метод load, запускать флаг isLoading True или False, но у MobX есть такой хелпер, который называется fromPromise.

      Мы объявляем некое поле, заворачиваем асинхронную операцию в хелпер fromPromise, и в этом поле появляется два сабполя — state и value.

      В React-компоненте можно сначала проверять, что state pending. Тогда мы показываем какой-то loading. Если fullfilled, тогда обращаемся к полю value и рисуем наш компонент дальше.

      Итого, плюсы MobX.

      Уже слышу вопрос из зала. Я этого человечка называю Reduxman, это человек, который написал много кода на Redux. Какой вопрос он задает?


      А как же netability? Это что же, у вас можно методами прямо полями модели менять? Ну ни фига себе.

      А как же time travel? Мне же нужны не модели с методами, а простые plain JavaScript-объекты, чтобы можно было с их помощью делать undo, redo и прочие вкусные штуки.

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

      Расскажу немного про Redux. Основные изменения, которые он произвел в головах разработчиков.

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

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

      Когда я начал думать, чем Redux отличается от MobX, у меня возникла такая аналогия.



      Все любили этот мультик? А чем отличаются мультики, которые смотрит молодое поколение? Они вот такие.



      Знаете, в чем разница? «Том и Джерри» рисовали таким образом, брали кадры и каждый рисовали по отдельности.

      Ничего не напоминает? Immutable store в Redux-приложении. Каждый раз есть какой-то отпечаток, который мы руками конструируем, используем для этого библиотеку immutable или Object.assign или spread operator. Каждый раз мы дорисовываем руками состояние приложения на текущий момент. Если нужно откатиться, мы берем и обратно откатываем. Это все круто, только очень много кода получается. Я не люблю писать код, я люблю его удалять. Код — это зло. Самый быстрый код — это тот, который не выполняется.

      А новые мультики рисуют вот так.



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

      То, что мы руками пытаемся работать с immutable-данными, — это необязательно. Immutable-состояние нашего приложения — это еще один вид, еще одно представление, еще одно отображение. Можно использовать живую модель, просто каждый раз в любой момент времени получить его плоскую проекцию.
      Давайте покажу, как это сделать.

      Авторы MobX написали такую отдельную штуку.

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

      Давайте напишем небольшой store, объявим класс Todo, для этого используется хелпер types, у которого есть метод model. Пока он пустой.

      Добавим title.

      Здесь мы объявляем, что это строка.

      Добавим опциональное булево поле isCompleted. Кстати, здесь есть возможность написать это короче. Если вы присваиваете какой-то примитив, то mobx-state-tree понимает, что это опциональное примитивное поле с дефолтным значением.

      Добавим reference. Это означает, что в folder будет лежать id какого-то другого объекта, но при создании модели mobx-state-tree по этому id достанет этот объект из некоего store и поставит его в этом поле. Пример я покажу чуть позже.


      Чтобы вся магия работала, нам нужно объявить класс Folder, у которого обязан быть id с типом types.identifier. Это как раз для того, чтобы связывать ссылки с объектами store по идентификатору.

      Объявим главный рутовый TodoStore, в котором будет два массива: todos и folders. Здесь можно видеть, как используется types.array, передаем в качестве аргумента класс, и MobX понимает, что это массив instance этого класса.

      Если мы объявляем геттер, он автоматически становится computed из терминологии MobX, как мы смотрели раньше. Здесь у меня есть геттер completedTodos, который просто возвращает список всех выполненных todo. Он кэшируется, и пока есть хоть один подписчик, он всегда возвращает закэшированное значение. Не бойтесь так писать, писать сложные выражения, все это будет закэшировано.

      Вот так создаются экшены. Первый объект в декларации — свойства и computed, во втором объекте перечислены экшены. Здесь и не надо их уже объявлять, mobx-state-tree по умолчанию считает, что все, что вы передаете вторым объектом, — экшены.

      Давайте попробуем создать store. У нас есть данные, допустим, они пришли с сервера, видите, они в нормализованном виде, у нас в folder лежит 1, а в списке folders есть объект с идентификатором 1.

      Создаем, используем.

      Первая строчка — все нормально, я использую поле title объекта todo.

      Во второй строчке уже магия: поскольку folder объявлен как reference, то MobX при создании модели автоматически, в первую очередь, положил folder в массив folders, а в моделях todo по ссылке, по идентификатору, добавил ссылку на этот объект. То, где в Redux мы бы писали селектор, здесь работает из коробки. Можно спокойно обращаться ко вложенным полям ваших ссылок, ваших референсов. И это работает, это очень удобно писать в компонентах без всяких селекторов и прочих map state to props.

      Мы собрали какую-то 3D-модель. Давайте попробуем запустить ее. Камера, мотор.

      Для начала попробуем получить обратно данные, которые мы в модель положили. Для этого есть хелпер getSnapshot. Передаем туда модель, получаем snapshot в виде обычного JS-объекта, как все редаксмены любят. Получил и получил, но у меня же модель постоянно меняется, как мне подписаться на изменения?

      Очень просто: есть хелпер onSnapshot, который позволяет подписаться на изменение любого поля в модели, при этом в качестве параметра он всегда передает новый snapshot, который он генерирует, но не просто так, иначе было бы глупо каждый раз новый объект генерировать. Он так же, как React, использует immutable.

      Если какие-то части менялись, он их реиспользует, запускает механизм structural sharing.

      Для изменившихся создает новые объекты.

      Как сделать time travel? Мы гуляем по истории и хотим какой-то snapshot применить к модели. Есть хелпер applySnapshot, передать модель, передать и snapshot. Он сравнивает то, что вы передали, и то, что сейчас в модели, берет диф и обновляет только те части, которые изменились.

      При этом он реиспользует модели, если у них совпадают идентификаторы. Если в модели лежит какой-то folders с id = 1, в snapshot тоже передается folders с id = 1. Он не пытается его перезатереть, а просто обновляет данные самого folder, если они изменились.

      Инстанция внутри модели не перезатирается, если вы правильно задали идентификаторы.

      Пожалуй, самая яркая иллюстрация того, как работают живые модели и snapshots.

      Есть живая модель, и мы в любой момент времени можем снять с нее snapshot.

      Наконец, бонус, специально для редаксменов. Есть для адаптера для работы с Redux. Если у вас уже есть большое приложение, написанное в Redux style, то вы можете переписать только store и из mobx-state-tree store получить reduxStore просто методом asReduxStore.

      Если вы привыкли работать с ReduxDevtools, можно просто использовать хелпер connectReduxDevtools, передать туда модель, store в виде mobx-state-tree, и все будет работать.

      Старые добрые ООП-модели вместо immutable-структур. Вообще-то, когда мы от них отказывались, кажется, мы выкинули ребенка вместе с водой. Они вообще-то были удобные, когда у вас есть данные и методы для работы с ними.

      Живые ссылки вместо селекторов. Вы можете вкладывать модели друг в друга сколько угодно, делать референсы и работать просто через точку. Todo.folder.parent и так далее, как хотите. При этом, когда вы будете сериализовывать, все будет автоматически обратно сериализовываться в нормализованный вид.

      Дешевое получение снэпшотов всего дерева с реиспользованием частей, которые не изменились. Применение снэпшотов с реконсайлингом, прямо как в React. Если объекты совпадают по идентификаторам, они будут реиспользованы. И — адаптеры для Redux Store и Redux Devtools.

      Как сказал Дэниел Эрвикер, MobX — это как React, только для данных. Здесь есть несколько ссылок, которые вы можете потом посмотреть:


      На этом спасибо.
      Original source: habrahabr.ru (comments, light).

      https://habrahabr.ru/post/339054/


      Метки:  

      Чтение на выходных: 17 независимых блогов по математике, алгоритмам и языкам программирования

      Воскресенье, 01 Октября 2017 г. 09:35 + в цитатник
      it_man сегодня в 09:35 Разработка

      Чтение на выходных: 17 независимых блогов по математике, алгоритмам и языкам программирования

        Сегодня мы подготовили очередную [наш IaaS-дайджест и материалы по структурированию кода] подборку полезных источников. На этот раз мы решили изучить тематическую ветку на Hacker News и рассказали о блогах, которые могут хорошо дополнить чтение «Хабра».

        Авторы данных блогов готовят как материалы для новичков с туториалами и разъяснениями основ, так и более углубленные статьи и исследования. Всех заинтересовавшихся приглашаем под кат.

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

        / Flickr / home thods / CC BY



        Математика и алгоритмы





        Сам автор блога Брайан Хэйс называет себя счастливчиком, которому удалось посвятить свою жизнь изучению математики и информатики. В своем блоге автор делится накопленным опытом (более 350 постов), а также пишет о биологии и физике, решает задачи и делится своим опытом работы с изображениями. С 1973-го по 1984-й год Брайан писал статьи для Scientific American – одного из старейших научно-популярных журналов США, который издается с 1845 года. Публикации Брайана выходили в «Computer Language» и «American Scientist». В 2005 году автор блога опубликовал книгу о промышленных объектах «Infrastructure: A Guide to the Industrial Landscape», а осенью 2017 года выйдет его новая книга «Foolproof, and Other Mathematical Meditations».




        Большая часть постов в блоге посвящена математике и информатике. Однако помимо упомянутых наук, автор также увлекается графикой (например, рассказывает, как рисовать орнамент из бабочек) и делится своим опытом рукоделия (например, описывает процесс рисования медузы на футболке). Совсем недавно автор издал книгу «Morphogenesis» с графическими изображениями на основе моделей сложных биологических рисунков. Черно-белые изображения для книги были вручную отобраны из 1000 сгенерированных вариантов.




        Эксперт в области прикладной математики, статистики и разработки программного обеспечения рассказывает простым и понятным языком, например о распределении Лапласа или Треугольнике Паскаля. Свой опыт решения проблем в упомянутых областях Джон смог применить на должности разработчика ПО в Онкологическом центре им. М. Д. Андерсона. Результаты работ автора доступны в виде статей, презентаций и, разумеется, в формате блог-постов. В настоящее время Джон оказывает консультационные услуги компаниям по всей Америке и регулярно пишет о наиболее интересных проблемах, задачах и разработках, с которыми ему довелось столкнуться.




        Автор блога, о котором мы рассказали выше, очень рекомендует всем блог Кевина Кнадсона. И пусть Кевин давно не обновлял свой блог (последняя публикация датируется 2015 годом), зато он успешно реализует проект под названием «My favorite theorem», в рамках которого он записывает подкасты в формате бесед с математиками со всех уголков мира. Рекомендуем к прослушиванию.




        Практически каждый из упомянутых выше блоггеров советует почитать «Discrete Analysis». Авторы журнала утверждают, что он совсем не похож на другие издания о математике. Отличия они видят в выдержанном тематическом фокусе и удобной подаче материала.




        Если вы хотите расширить свои знания в области квантовой механики и высшей математики, Дэн Пипони поможет вам в этом. В своем блоге автор старается уйти от нудных объяснений и использует примеры из обычной жизни, подкрепляя их схемами. Сам автор разбирает примеры на Haskell, однако, материалы по линейной алгебре, логике и многим другим темам, интересно почитать, даже если вы работаете с другими языками. В профиле автора на Google+ или в его Twitter можно узнать о жизни автора, найти посты с интересными ссылками на статьи (например, о проверке гипотез с помощью P-значения).


        / Flickr / home thods / CC BY



        Языки программирования





        Блог, который с 2005 года ведет Майк Эш, особенно приглянется тем, кто пишет на Swift. В блоге вы найдете руководства, разборы ошибок и заметки с тематических семинаров. Майк регулярно отвечает на вопросы читателей и составил целую книгу из еженедельных Q&A-постов. Она называется «The Complete Friday Q&A: Volume I».




        Руководства на Python, Haskell и Clojure от Эли Бендерски. Этот проект начался в качестве персонального блога в 2003 году и перерос в технологический журнал, с помощью которого автор «прокачивает» свои знания и делится открытыми проектами.




        В блоге Стивена Дила можно найти примеры решения задач на Haskell с подробными объяснениями и примерами кода. Кроме того, автор предлагает проверенные им лично ресурсы для погружения в особенности языка. И пусть в блоге не так много постов, зато каждый их них написан с вниманием к деталям.




        Карин Майер, разработчик ПО, пишет о Clojure, искусственном интеллекте и робототехнике. Кстати, совсем недавно в мае 2017 автор блога опубликовала книгу «Code Shifter», которую написала вместе со своей дочерью. Книга описывает приключения 12-летней девочки Элизы, обладающей способностью изменять код одним только прикосновением. Во время этих приключений Элиза вместе с друзьями учится программировать и познает свои сильные стороны.




        Фред Херберт, автор книги «Изучай Erlang во имя добра» (Learn You Some Erlang for Great Good!) в своем блоге разбирает ошибки и делится руководствами на Erlang.




        Блог польского разработчика Бартоломея Филипека (Bartlomiej Filipek, он же Bartek) будет интересен тем, кто ищет регулярно обновляющийся ресурс о С++. Бартек начал писать код, когда ему было 14, поэтому за спиной у него немалый опыт работы в самых разных областях: от разработки ПО до геймдева. В блоге можно найти посты об оптимизации, практические советы, последние стандарты и много чего еще. Например, вот эта статья Бартека была признана одной из лучших на англоязычной тематической площадке за январь 2016.




        Название блога говорит само за себя. Внутри вы найдете руководства для написания чистого кода на С++. Автор блога, Джонатан Боккара (Jonathan Boccara), делится своим 5-летним опытом программирования на С++, и методами обучения сотрудников.




        Блог Роберта Харпера, профессора кафедры теории и практики вычислительных машин и систем Университета Карнеги-Меллон, будет интересен тем, кто хотел бы погрузиться в теорию языков программирования. Особенно много информации можно найти по SML и grid-вычислениям. Профессор Харпер также является автором нескольких книг, среди которых «The Definition of Standard ML» и «Practical Foundations for Programming Languages».




        В блоге Криса Дала вы сможете познакомиться с самыми различными языками вроде Pony, Vodka или Haskell. Помимо этого в своем блоге Крис разбирается с ОС, браузерами и сетевыми технологиями. Обычно он проводит детальный анализ того или иного предмета, сопровождая его кодом и пояснениями, а также подкрепляет свое мнение ссылками на полезные ресурсы. В блоге около трехсот публикаций, накопленных за 12 лет.




        Название этого блога плавно эволюционировало из «Inside 245s». До этого он назывался: Inside T5, Inside P4, Inside 1712B, Inside 2214, Inside 233, Inside 374, Inside 206-105, Inside 214-1E и Inside 245-5D. Автор этого блога, Эдвард З. Ян (Edward Z. Yang), эволюционировал вместе с ним. Сейчас он — аспирант Стэнфордского университета и автор нескольких публикаций. Больше всего блоггер интересуется Haskell (например, в блоге есть иллюстрированное введение в работу на Haskell).




        В «стране Ruby» вы найдете свежие новости, туториалы и мнения экспертов об одном из самых молодых и популярных языков программирования. Ресурс обновляется несколько раз в день — это одна из лучших тематических лент о Ruby. Автор проекта Джонатан Рочкинд (Jonathan Rochkind) регулярно публикует посты в своем блоге о Ruby и веб-разработке, а апдейты Rubyland также доступны и в Twitter.



        P.S. Наши дайджесты:


        P.P.S. О чем еще мы пишем в нашем корпоративном блоге:

        Original source: habrahabr.ru (comments, light).

        https://habrahabr.ru/post/338624/


        Метки:  

        DevOps приходит к нам домой? Домашний Minecraft server в Azure с применением современных DevOps практик

        Суббота, 30 Сентября 2017 г. 23:04 + в цитатник
        Dronopotamus вчера в 23:04 Разработка

        DevOps приходит к нам домой? Домашний Minecraft server в Azure с применением современных DevOps практик

        • Tutorial
        Эта статья НЕ про майнкрафт. Эта статья про Azure и про современные подходы к деливери ПО.

        Если вы просто хотите развернуть себе сервер майнкрафт — спросите гугл «minecraft server hosting» — будет и проще и дешевле.

        А вот если вы хотите посмотреть на реальный кейс использования подходов Infrastructure as Code, Configuration as Code применительно к неадаптированному к Azure ПО на примере майнкрафта — то добро пожаловать

        Roadmap


        Azure Stack огромен и хочется потыкать в разные его части, поэтому эта статья будет всяко не одна.

        План статей пока видится такой:

        • Автоматизированный деплой и настройка сервера с применением Azure CLI 2 и Powershell DSC
        • Поддержка конфигурации сервера в консистентном состоянии с применением Azure Automation
        • Автоматизированное обновление сервера на новую версию
        • Получение логов майнкрафта, анализ и отображение с применением Azure Stream Analytics и Power BI
        • Организация active/passive кластера с управлением через Azure Automation
        • ...

        Но конечно процесс появления новых статей может быть остановлен отсутствием вашего интереса )

        Disclaimer


        • Я не it инженер, не devops инженер, не игрок в майнкрафт. Поэтому если вы шарите и вам кажется, что я всё делаю не правильно — то скорее всего так оно и есть — напишите в коментах как надо.
        • Все примеры к статье 100% рабочие, но поставляются «как есть». Если у вас что-то не работает — почините это самостоятельно или забейте.

        Итак.

        Автоматизированный деплой и настройка сервера с применением Azure CLI 2 и Powershell DSC


        О задаче


        Задача не синтетическая. Сервер попросили развернуть дети и он реально будет использоваться. Меньше всего я хочу его постоянно чинить и поднимать. Ещё меньше я хочу терять данные при обновлениях. Поэтому требования к нему вполне себе prod-like )

        Общий подход


        • 100% автоматизация.
        • Относимся к скриптам как к коду
        • Соблюдаем базовые требования конфигурационного управления к деливери процессу на prod окружения

        Все пункты буду пояснять по ходу дела

        О ПО


        В качестве сервера я взял официальный сервер minecraft.net/en-us/download/server. Беглое изучение выявило, что:

        • Сервер представляет из себя jar файл и требует для запуска java
        • Для запуска ему требуется рядом с собой файл eula.txt с определённым содержимым
        • Сервер конфигурируется с помощью файла server.properties который тоже должен лежать рядом
        • Сервер слушает 25565 порт по протоколу TCP
        • Данные (карту) сервер хранит в папочке World рядом с собой (и это будет слегка проблемой)
        • Сервер умеет данные апгрейдить, если они созданы предыдущей версией (и это сильно упростит жизнь при апгрейде)
        • Логи хранятся в папочке Logs рядом

        Инфраструктура


        Применим самую базовую схему:

        одна Resource Group c:

        • Network Security Group (будут открыты порты 25565 (minecraft) и 3389 (rdp)
        • VNET c 1 subnet
        • NIC и статический public IP c DNS именем
        • 1 VM под Windows Server 2016 core + 2 Managed Disk (OS + Data)
        • Storage account и 1 container для Blob storage

        image

        Данные будем хранить отдельно от виртуальной машины на отдельном managed disk и линковать в папочку World рядом с jar'кой с помощью Symlink (я писал выше, что расположение папочки world не настраивается и должно быть всегда рядом с jar).

        Это даст возможность запускать сервер как с прилинкованным диском, так и без (для тестов) — в этом случае папка world будет создана с пустой картой.

        Сервер будем конфигурировать на основании:

        • Дистрибутива (jar с сервером + jre + начальные данные), который будет предварительно загружаться в Blob storage
        • Конфигурации (Powershell DSC), которая также будет предварительно загружаться в Blob storage

        Я там выше обещал следования некоторым требованиям конфигурационного управления — вот первое:

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

        Именно поэтому мы и дистрибутив и конфигурацию будем предварительно собирать из артефактов в интернетах и перепубликовывать в Blob Storage.

        Таким образом, алгоритм процедуры развертывания следующий:

        • Создать новую Resource Group, Storage Account и Storage Container
        • Сформировать дистрибутив (jar с сервером + jre + начальные данные) и загрузить его в Blob Storage
        • Создать всю остальную инфраструктуру в Resource Group
        • Сформировать DSC конфигурацию и загрузить её в Blob Storage
        • Сконфигурировать сервер на основании конфигурации и дистрибутива

        Исходники


        • Храним на github
        • Соблюдаем какую-нибудь внятную стратегию бранчевания и релизного цикла (ну например gitflow и релиз каждую статью :))
        • Используем azure cli 2 и bash там, где это возможно (к слову, в этой статье удалось совсем избежать использования powershell api. А вот в следующей это уже не получится)

        Реализация шагов процедуры развертывания


        1. Создать новую Resource Group, Storage Account и Storage Container


        реализация тривиальная, просто вызовы cli

        initial_preparation.sh
        az configure --defaults location=$LOCATION group=$GROUP
        
        echo "create new group"
        az group create -n $GROUP
        
        echo "create storage account"
        az storage account create -n $STORAGE_ACCOUNT --sku Standard_LRS
        STORAGE_CS=$(az storage account show-connection-string -n $STORAGE_ACCOUNT)
        export AZURE_STORAGE_CONNECTION_STRING="$STORAGE_CS"
        
        echo "create storage container"
        az storage container create -n $STORAGE_CONTAINER --public-access blob


        2. Сформировать дистрибутив (jar с сервером + jre + начальные данные) и загрузить его в Blob Storage


        Скачиваем сервер и карту, jre берём с текущего компьютера и всё пакуем в zip
        структура дистрибутива:

        • .jar
        • jre
        • initial_world — папка с начальной картой

        prepare_distr.sh
        mkdir $DISTR_DIR
        cd $DISTR_DIR
        
        echo "download minecraft server from official site"
        curl -Os https://s3.amazonaws.com/Minecraft.Download/versions/1.12.2/minecraft_server.$MVERSION.jar 
        
        echo "copy jre from this machine"
        cp -r "$JRE" ./jre
        
        echo "create ititial world folder"
        mkdir initial_world
        cd initial_world
        
        echo "download initial map"
        curl -Os https://dl01.mcworldmap.com/user/1821/world2.zip 
        unzip -q world2.zip
        cp -r StarWars/* .
        rm -r -f StarWars
        rm world2.zip
        cd ../
        
        echo "create archive (zip utility -> https://ranxing.wordpress.com/2016/12/13/add-zip-into-git-bash-on-windows/)"
        cd ../
        zip -r -q $DISTR_ZIP $DISTR_DIR 
        rm -r -f $DISTR_DIR
        


        3. Сформировать DSC конфигурацию и загрузить её в Blob Storage


        DSC конфигурация представляет собой один ps1 файл (о структуре его — позже), который будет запускаться на сервере и его конфигурировать.

        Но скрипты в ps1 файле имеют депенды на внешние модули, которые не будут установлены на сервер автоматически.

        Поэтому конфигурацию надо передать на сервер не просто как ps1 файл, а как архив с:

        • ps1 файлом
        • Всеми зависимыми модулями, сложенными в одноименных папочках рядом с ps1 файлом

        Зависимые модули можно просто скачать curl'ом как nuget пакет с репозитория powershell gallery и разархивировать в нужное место.

        Также можно использовать и команду powershell Save-Module — которая включает эти два шага
        Обратите внимание, что версии зависимых модулей и в ps1 файле и в скриптах формирования архива с конфигурацией указаны и совпадают.

        И тут мы опять следуем требованиям очередного правила конфигурационного управления:

        Все зависимости должны быть точно определены и ресолвиться всегда однозначно

        prepare_config.sh
        echo "prepare server configuration"
        curl -s -L -o configuration/xPSDesiredStateConfiguration.zip "https://www.powershellgallery.com/api/v2/package/xPSDesiredStateConfiguration/7.0.0.0"
        curl -s -L -o configuration/xNetworking.zip "https://www.powershellgallery.com/api/v2/package/xNetworking/5.1.0.0"
        curl -s -L -o configuration/xStorage.zip "https://www.powershellgallery.com/api/v2/package/xStorage/3.2.0.0"
        cd configuration
        
        unzip -q xPSDesiredStateConfiguration.zip -d xPSDesiredStateConfiguration
        rm -r xPSDesiredStateConfiguration.zip
        unzip -q xNetworking.zip -d xNetworking
        rm -r xNetworking.zip
        unzip -q xStorage.zip -d xStorage
        rm -r xStorage.zip
        
        zip -r -q ../$CONFIG_ZIP . *
        rm -r -f xPSDesiredStateConfiguration
        rm -r -f xNetworking
        rm -r -f xStorage
        cd ../


        4. Создать всю остальную инфраструктуру в Resource Group


        реализация тривиальная, просто вызовы cli:

        iaas_preparation.sh
        
        echo "create network security group and rules"
        az network nsg create -n $NSG
        az network nsg rule create --nsg-name $NSG -n AllowMinecraft --destination-port-ranges 25556 --protocol Tcp --priority 100
        az network nsg rule create --nsg-name $NSG -n AllowRDP --destination-port-ranges 3389 --protocol Tcp --priority 110
        
        echo "create vnet, nic and pip"
        NIC_NAME=minesrvnic
        PIP_NAME=minepip
        SUBNET_NAME=servers
        az network vnet create -n $VNET --subnet-name $SUBNET_NAME
        
        az network public-ip create -n $PIP_NAME --dns-name $DNS --allocation-method Static
        az network nic create --vnet-name $VNET --subnet $SUBNET_NAME --public-ip-address $PIP_NAME -n $NIC_NAME 
        
        echo "create data disk"
        DISK_NAME=minedata
        az disk create -n $DISK_NAME --size-gb 10 --sku Standard_LRS
        echo "create server vm"
        az vm create -n $VM_NAME --size $VM_SIZE --image $VM_IMAGE \
                        --nics $NIC_NAME \
                        --admin-username $VM_ADMIN_LOGIN --admin-password $VM_ADMIN_PASSWORD \
                        --os-disk-name ${VM_NAME}disk --attach-data-disk $DISK_NAME                


        5. Сконфигурировать сервер на основании конфигурации и дистрибутива


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

        DSC extension кормится конфигом в котором указан URL до архива с конфигурацией и значения параметров

        server_configuration.sh
        echo "prepare dsc extension settings"
        cat MinecraftServerDSCSettings.json | envsubst > ThisMinecraftServerDSCSettings.json
        
        echo "configure vm"
        az vm extension set \
           --name DSC \
           --publisher Microsoft.Powershell \
           --version 2.7 \
           --vm-name $VM_NAME \
           --resource-group $GROUP \
           --settings ThisMinecraftServerDSCSettings.json
        rm -f ThisMinecraftServerDSCSettings.json


        О Powershell DSC


        Ну это некоторая надстройка над powershell, которая позволяет декларативно описывать требуемое состояние компьютера.

        DSC конфигурация анализируется на целевой машине, строится диф относительно текущей конфигурации этой машины, а затем происходит приведение конфигурации к нужной. Ближайший аналог powershell DSC в «opensource» мире — Ansible.

        Реализация DSC конфигурации MinecraftServer


        Структурно конфигурация состоит из набора шагов, которые выполняются в определенном порядке (с учётом зависимостей). Пробежимся по всем:

        xRemoteFile DistrCopy
        {
           Uri = "https://$accountName.blob.core.windows.net/$containerName/mineserver.$minecraftVersion.zip"
           DestinationPath = "$mineHome.zip"
           MatchSource = $true
        }
        

        Декларирует, что на компьютере должен лежать zip с дистрибутивом сервера по пути DestinationPath, если его там не лежит — он будет скачен по адресу Uri:

        Archive UnzipServer 
        {
           Ensure = "Present"
           Path = "$mineHome.zip"
           Destination = $mineHomeRoot
           DependsOn = "[xRemoteFile]DistrCopy"
           Validate = $true
           Force = $true
        }
        

        Декларирует, что на компьютере в папке Destination должен лежить разархивированный архив с дистрибутивом сервера если его там не лежит (или если состав файлов отличается от того что в архиве) — они будут добавлены:

        File CheckProperties
        {
           DestinationPath = "$mineHome\server.properties"
           Type = "File"
           Ensure = "Present"
           Force = $true
           Contents = "....."
        }
        
        File CheckEULA
        {
           DestinationPath = "$mineHome\eula.txt"
           Type = "File"
           Ensure = "Present"
           Force = $true
           Contents = "..."				
           DependsOn = "[File]CheckProperties"
        }
        

        Декларирует, что по пути DestinationPath должны лежать файлы с конфигом сервера и с лицензией. Если их нет — они создаются с содержимым Contents:

        xWaitForDisk WaitWorldDisk
        {
           DiskIdType = "Number"
           DiskId = "2"   
           RetryIntervalSec = 60	
           RetryCount = 5
           DependsOn = "[File]CheckEULA"
        }
        
        xDisk PrepareWorldDisk
        {
           DependsOn = "[xWaitForDisk]WaitWorldDisk"
           DiskIdType = "Number"
           DiskId = "2"
           DriveLetter = "F"
           AllowDestructive = $false
        }
        
        xWaitForVolume WaitForF
        {
           DriveLetter      = 'F'
           RetryIntervalSec = 5
           RetryCount       = 10
           DependsOn = "[xDisk]PrepareWorldDisk"
        }
        

        Тут мы декларируем о том, что managed disk с данными должен быть инициализирован в OS и ему должна быть присвоена буква F:

        File WorldDirectoryExists
        {
           Ensure = "Present" 
           Type = "Directory"
           Recurse = $true
           DestinationPath = "F:\world"
           SourcePath = "$mineHome\initial_world"
           MatchSource = $false
           DependsOn = "[xWaitForVolume]WaitForF"    
        }
        

        Декларируем о том, что на диске F должна присутствовать директори world (с миром). Если её там нет — мы считаем что происходит деплой впервые и нам надо эту папку создать, взяв за основу карту из initial_world дистрибутива:

        Script LinkWorldDirectory
        {
           DependsOn="[File]WorldDirectoryExists"
           GetScript=
           {
              @{ Result =  (Test-Path "$using:mineHome\World") }
           }
           SetScript=
           {
              New-Item -ItemType SymbolicLink -Path "$using:mineHome\World" -Confirm -Force -Value "F:\world"                
           }
           TestScript=
          {
              return (Test-Path "$using:mineHome\World")
           }
        }
        

        Это кастомный шаг — проверяем, что у нас в папке с сервером есть папка World. Если её нету — линкуем её с диска F. Script работает следующим образом — если TestScript вернул false — вызывается SetScript. Иначе не вызывается:

        Script EnsureServerStart
        {
           DependsOn="[Script]LinkWorldDirectory"
           GetScript=
           {
              @{ Result = (Get-Process -Name java -ErrorAction SilentlyContinue) } 
           }
           SetScript=
           {
              Start-Process -FilePath "$using:mineHome\jre\bin\java" -WorkingDirectory "$using:mineHome" -ArgumentList "-Xms512M -Xmx512M  -jar `"$using:mineHome\minecraft_server.$using:minecraftVersion.jar`" nogui"                
           }
           TestScript=
           {
              return (Get-Process -Name java -ErrorAction SilentlyContinue) -ne $null
           }
        }
        

        Ещё один кастомный шаг. Проверяем, что запущен java процесс с сервером ). Если не запущен — запускаем:

        xFirewall FirewallIn 
        { 
           Name = "Minecraft-in"             
           Action = "Allow" 
           LocalPort = ('25565')
           Protocol = 'TCP'
           Direction = 'Inbound'
        }
        
        xFirewall FirewallOut 
        { 
           Name = "Minecraft-out"             
           Action = "Allow" 
           LocalPort = ('25565')
           Protocol = 'TCP'
           Direction = 'Outbound'
        }

        И последние шаги — открываем 25565 порт.

        Эпилог


        Статья получилась и так длинная, надо закругляться. Остались за бортом вопросы дебага этого DSC (очень интересные сами по себе) — освещу их в следующей.

        Всем спасибо за внимание.

        Как всё это запустить из Windows
        Нам нужен будет


        Запуск процедуры ролаута

        git clone https://github.com/AndreyPoturaev/minecraft-in-azure
        cd minecraft-in-azure
        git checkout v1.0.0
        export MINESERVER_PASSWORD=
        export MINESERVER_DNS=
        export MINESERVER_STORAGE_ACCOUNT=
        az login
        . rollout.sh
         

        Результат:

        image
        Original source: habrahabr.ru (comments, light).

        https://habrahabr.ru/post/339034/


        Метки:  

        История создания синхронизатора часов DCF77

        Суббота, 30 Сентября 2017 г. 21:11 + в цитатник

        Метки:  

        Как довести первый проект до конца. Часть 2. Мифы, ошибки и провалы

        Суббота, 30 Сентября 2017 г. 19:25 + в цитатник


        Здравствуйте! Я уже рассказывал в первой статье и интермедиальной статье, как довести свой первый проект до конца. Но в итоге я понял, что эти статьи касаются в первую очередь разработки. А как же продвижение?

        И сейчас мы рассмотрим мифы и ошибки, на которых я споткнулся. И, хотя игру хвалили многие, она на момент написания статьи получила только 61 загрузку!

        Ну вот как так может быть? Читать дальше ->

        https://habrahabr.ru/post/339044/


        Метки:  

        [CppCon 2017] Бьёрн Страуструп: Изучение и преподавание современного C++

        Суббота, 30 Сентября 2017 г. 19:13 + в цитатник
        Fil сегодня в 19:13 Разработка

        [CppCon 2017] Бьёрн Страуструп: Изучение и преподавание современного C++

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


          Это первое вступительное видео. Оно не такое интересное для меня, но пропустить тоже не мог, это же Страуструп. Далее, текст от его лица. Заголовки взяты из слайдов.





          Disclaimer: весь дальнейший текст — достаточно краткий пересказ, являющийся результом работы моего восприятия, и то, что я посчитал "водой" и проигнорировал, могло оказаться важным для вас. Иногда выступление было таким: "(важная мысль 1)(минута воды)(важная мысль 2)". Эти две мысли плавно перетекали друг в друга, а у меня получались довольно резкие скачки. Где можно сгладил, но посчитал нецелесообразным полностью причесывать текст, на это бы потребовалось много времени.


          Вступление


          Когда меня попросили выступить на открытии конференции, я задумался, о чем же я могу рассказать такого, что важно для вас, и чего вы не слышали миллион раз. И я решил рассказать про обучение языку C++.


          Мы все учителя и мы все ученики


          Зададимся вопросом кого мы учим, чему, зачем и как. Нужно делать это лучше. Я не критикую кого-то в частности, но чувствую, что мы должны делать это лучше. Не все из нас преподаватели, но тем не менее постоянно возникают случаи, когда мы занимаемся обучением. Например, рассказываем коллегам о последних фичах или даем советы. Общаемся на StackOverflow, Reddit, ведем блоги и т.д. Но нужно давать хорошие советы. Советы, которые двигают мир вперед.


          Есть одна вещь, которая сильно беспокоит меня — зачастую у людей бывают очень странные представления о том, что собой представляет C++. Чуть позже я вернусь к этой проблеме.


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


          Обучение программированию


          Не нужно фокусироваться на языковых фичах. Например, вы встречали примеры в которых объясняется проблема приведения signed short к unsigned int [рассказывается о преподавании языка в общем, а не об особенностях C++]. Это неинтересно и можно увидеть в отладчике или прочитать в руководстве. Учите так, чтобы такая проблема не появлялась.


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


          Одна из встечающихся проблем обучения C++ — то что язык изучается сам по себе, отдельно от библиотек. Вектор на 697 странице, sort через 100 страниц. Это учит, что stl скучная, сложная фигня. И в то же время: свой Linked List или Hash table это круто, круче чем stl.


          Не будьте слишком умными


          [в выступлении автор использует слово clever с негативным оттенком, что-то вроде человека, который пытается казаться быть умным]


          Люди которые хотят и требуют "самое последнее" часто не знают основ. Пересмотрите основы.


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


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


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


          Обучение программированию


          Если изучать только сам язык, то попав в реальность можно просто "утонуть".
          Используйте различные инструменты. Не только компилятор и учебник, но и IDE, отладчики, системы контроля версий, профилировщики, модульное тестирорвание, статические анализаторы, онлайн компиляторы. Интрументы должны быть современными (иногда получаю вопросы по Turbo C++ 4.0 :( )


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


          Язык это не только синтаксис


          Как мы часто учим? Объясняем язык плюс немного стандартную библиотеку. Без всякой графики, пользовательского интерфейса, веба, электронной почты, баз данных… И многие ученики считают, что C++ скучный бесполезный язык. Но это же не так, ведь такие вещи как браузеры, СУБД, САПР и прочие пишутся на C++. Перед началом лекции потратьте 5 минут о практическом применении.


          Мы должны сделать лучше


          Нам, сообществу C++, очень важно упростить начало работы, возможность пользоваться "прямо сейчас".


          Как программирование похоже на занятие фотографией?


          Как пользователи в различных отраслях разделяются на группы? Приведем пример с фотографией. Результат зависит от оборудования и от пользователя. Лично я новичок в фотографии. Большинство возможностей профессиональной фотокамеры будут для меня бесполезными. Она много весит, дорого стоит. Для нее существует множество аксессуаров в которых можно утонуть. Но с ее помощью можно делать превосходные фотографии, если потратить много времени на обучение. Аналогично существует много людей, которые не могут использовать разнообразные фичи языка и библиотеки.


          Массовый рынок


          С другой стороны, у нас есть устройства, которыми можно пользоваться сразу. Такое устройство дешевое, простое, "милое". Прощает ошибки, не требует много усилий для освоения. Является "вещью в себе". Мало расширений и дополнений, если таковые вообще есть. Отсуствуют взаимозаменяемые части.


          Как-то во время преподавания мне было нужно, чтобы у студентов была установлена библиотека GUI. Оказалось, что установить одну и ту же библиотеку на студенческие Mac, Linux, Windows, весьма болезненно.


          Языку нужна "система"


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


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


          Какими должны быть основные дистрибутивы?


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


          Модули помогут


          База:


          import bundle.entry_level; //Для новичков
          import bundle.enthusiast_level; //Для продвинутых
          import bundle.professional_level; //Для профессионалов

          Расширения (которые не входят в базу):


          import grahics.2d;
          import grahics.3d;
          import professional.graphics.3d;
          import physlib.linear_algebra;
          import boost.XML;
          import 3rd_party.image_filtering;

          Нужны хорошие пакетные менеджеры и системы сборки


          Как ученик на вторую неделю после начала обучения может установить библиотеку графического интерфейса и работы с базами данных? Различные библиотеки и системы собираются по разному. Различные библиотеки могут быть плохо совместимыми. Десяток несовметимых пакетных менеджеров — это не решение. Нужно сделать простым выполнение простых задач


          > download gui_xyz
          > install gui_xyz

          Или эквивалетным способом, например в IDE:


          import gui_xyz; //в коде

          Современный C++


          Мое видение современного C++ (как обычно):


          • Статическая типобезопасность, хорошо определенные интерфейсы.
          • Безопасность ресурсов (конструкторы/деструкторы, RAII).
          • Абстракции без накладных расходов.
          • Инкапсуляция, инварианты.
          • Обобщенное программирование, шаблоны.
          • Простота для большинства разработчиков, сложность скрыта в библиотеках.

          Меняться трудно


          Современный C++ это не C, Java, C++98 и не тот язык, на которым вы программировали 10 лет назад. Инерция — враг хорошего кода. Преподаватели, оправдывая неиспользование современных стандартов, говорят, что "мы так не делаем", "это не вставить в мою учебную программу", "может быть через 5 лет". У студентов появляется большее доверие к интернету, чем к преподавателям. Некоторые считают, что они умнее преподавателей, и иногда они правы. У меня стабильно каждый год на курсе были студенты, абсолютно убежденные, что они умнее меня в программировании. В этих частных случаях, я обоснованно уверен, что оне не правы [смех в зале].


          Что такое современный С++?


          • Лучшие практики, использующие текущий стандарт ISO С++
          • Стремление к типо- и ресурснобезопасному коду

          Для реализации этого 2 года назад был открыт проект C++ Core Guidelines. Он дает конкретные ответы на вопросы. У него много много участников, включая Microsoft и Red Hat.


          Примеры кода


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


          Улучшение кода


          Всегда объясняйте причины. Например:


          //1
          int max = v.size();
          for(int i = 0; i < max; ++i)
          
          //2
          for (auto x : v)

          Почему 2 лучше чем 1? Пример 2 явно показывает намерение, v может быть изменен без переписывания цикла, и менее подвержен ошибкам. Следует заметить, что 1 предоставляет более гибкие возможности. Но ведь goto еще более универсален, и поэтому мы избегаем его.


          • I.4: Делайте интерфейсы точными и строготипизированными

          [I.4 означает пункт из Core Guidelines]


          void blink_led1(int time_to_blink) //Плохо - неясный тип
          
          void blink_led2(milliseconds time_to_blink) //Хорошо
          
          void use()
          {
            blink_led2(1500); //Ошибка: какая единица измерения?
            blink_led2(1500ms);
            blink_led2(1500s); //Ошибка: неверная единица измерения
          }

          [Здесь milliseconds какой-то простой тип не из библиотеки Chrono, поэтому последняя строчка приводит к ошибке. Ниже по тексту описано обобщение типа для единицы измерения, взятого из Chrono. Если интересно, можете почитать мое описание этой библиотеки]


          template
          void blink_led(duration time_to_blink)
          {
            auto ms_to_blink = duration_cast(time_to_blink);
          }
          
          void use()
          {
            blink_led(2s);
            blink_led(1500ms);
          }

          • ES.20: Всегда инициализируйте объект
          • F.21: Для возврата нескольких значений из функций предпочитайте использовать tuple, структуру (или structured binding).

          Error_code err; //неинициализировано: потенциальная проблема
          //...
          Channel ch = Channel::open(s, &err); //out-параметр: потенциальная проблема
          if(err) { ... }
          
          Лучше:
          auto [ch, err] = Channel::open(s) //structured binding
          if(err) ...

          А должен ли этот код использовать возврат двух параметров?


          • E.1: Прорабатывайте стратегию отлова ошибок в начале разработки
          • E.2: Бросайте исключение для уведомления того, что функция не может выполнить задачу
          • E.3: Используйте исключения только для уведомления об ошибках

          auto ch = Channel::open(s);

          Лучше? Да, если неуспешное открытие было предусмотрено в программе.


          Улучшение кода: не будьте слишком умными


          Слово "умный" в контексте использования C++ — ругательное. Найдите баг:


          istream& init_io()
          {
              if(argc > 1)
                  return *new istream { argv[1], "r" };
              else
                  return cin;
          }

          • P.8: Не допускайте утечки
          • R.11: Избегайте прямого вызова new и delete
          • R.4: Raw-ссылка (T&) должны быть невладеющей

          Комментирование


          • P.1: Выражайте идеи прямо в коде
          • NL.1: Не говорите в комментариях, что и так ясно видно в коде
          • NL.2: Выражайте намерения в комментариях
          • NL.3: Поддерживайте комментарии в актуальном состоянии

          //Плохо
          auto x = m * v1 + vv //Перемножение m с v1 и прибавление vv
          
          //Хорошо
          void stable_sort(Sortable& c)
          //cортирует "c" согласно порядку, задаваемым "<"
          //сохраняет исходный порядок равных элементов (определяемыми "==")
          {
              //...несколько строк нетривиального кода
          }

          Philosophy rules


          Я рекомендую вам отправиться на github и почитать раздел Philosophy rules, содержащий основные концепции.


          Core guidelines


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


          Сейчас разрабатываются 2 открытых проекта: анализатор, для проверки провил Core Guidelines, и библиотека GSL — guidelines support library (реализация от Microsoft).


          No Garbage Collector!


          Вопросы? Комментарии?


          Нет, я расказал далеко не все про обучение. Лишь едва царапнул поверхность.


          Вопросы из зала


          [У Страуструпа есть сверхспособность отвечать по 5 минут на простые вопросы, поэтому я очень сильно сократил его ответы да и сами вопросы тоже]


          Core Guidelines слишком всеобъемлющие. как учить?

          Не нужно читать всё. Прочитать введение, затем раздел с философией. Не нужно искать правило, правило само найдет вас.


          Нужны ли стандартной библиотеке нужны простые функции? Например random [я полагаю, что имеется в виду функция без необходимости установки начального значения и возможностью задания закона распределения]?

          Да, нужны.


          Вы говорили про 3 дистрибутива C++. Кто должен этим заниматься?

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


          Моя дочь учится в колледже и мы вместе делали проект термостата. Так вот, для того, чтобы получить температуру и отобразить на экране, потребовался целый семестр изучения C++. Что вы думаете по этому поводу?

          Да, есть такая проблема. С модулями будет лучше.


          Нужно ли преподавать программирование как общий предмет, так же как математику

          Я не компетентен в этом вопросе.


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

          Зависит от цели. Я учу студентов как реализовать вектор, они должны знать об указателях, но не каждому нужно реализовывать lock-free код.

          Original source: habrahabr.ru (comments, light).

          https://habrahabr.ru/post/339036/


          Метки:  

          Продолжение поста от школьников. Как Хабрахабр смог изменить нашу судьбу?

          Суббота, 30 Сентября 2017 г. 17:06 + в цитатник
          Noobariouse сегодня в 17:06 Разработка

          Продолжение поста от школьников. Как Хабрахабр смог изменить нашу судьбу?

            К посту: habrahabr.ru/post/338596

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

            image

            Вступление


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

            Что насчет рекламы?


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

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

            После этого статью моментально подхватило около 20 сайтов-агрегаторов новостей, которые очень быстро разнесли материал по интернету. Статья появилась в таких новостных гигантах, как Яндекс.Дзен и Flipboard, а также на многих других сайтах.

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

            Что там с Google Play?


            Также у нас была большая проблема с отзывами — их не было видно на главной странице игры, так как большинство игроков оставляли отзывы еще при бета-тестировании игры. А отзывы бета-теста на релизной версии приложения не видны. Из-за этого вид страницы на Google Play не привлекал новых пользователей, так как у них складывалось впечатление, что игра полнейший ноунейм. И тут участливые хабравчане тоже не остались в стороне.

            Мы сидели и читали отзывы, которые приходили с Хабра каждые 5 минут примерно с таким видом:


            Надо отметить, что у игры возрос средний рейтинг и перевалил за 4,5 звезды.
            Из-за этого загрузки, а соответственно и показатели игры в общем рейтинге Гугла начали стремительно расти вверх.
            К сравнению: если на момент публикации игры, мы на старте попали на 280 место в ТОПе новых приложений и на 260 место в ТОПе новых игр, то сейчас мы уже занимаем места в первой половине сотни в обоих топах.

            Что в итоге? Наши планы на будущее.


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

            Скажем сразу, что если у нас что-то и получится с созданием своего бизнеса, то мы 100% будем делать его в России, так как мы тут выросли. И мы очень благодарны нашей стране, которая дала нам образование, а также много-много возможностей. Ну и вообще, нам тут просто очень нравится.
            И сейчас, во время сложной экономической ситуации в стране, нам кажется, что пришло самое время её отблагодарить, сделать что-то полезное в ответ. Мы хотим сделать то, что поможет России в такой непростой ситуации, возможно, даже привлечет в нее иностранных инвесторов.

            Непосредственно благодарность!


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

            Спасибо вам огромное!


            image
            Original source: habrahabr.ru (comments, light).

            https://habrahabr.ru/post/339030/


            Метки:  

            [Из песочницы] Необразованная молодёжь

            Суббота, 30 Сентября 2017 г. 13:45 + в цитатник
            aleshqqa1337 сегодня в 13:45 Разное

            Необразованная молодёжь

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

            Так получилось, что после окончания 9 класса, я поступил в колледж по профессии «Прикладная информатика по отраслям». Колледж — филиал хорошего института в северной столице нашей страны. Выбор был осознанный и я с детства интересовался информатикой. После зачисления, радости не было придела. Воображал себя сидя за компьютером в каком-нибудь крутом офисе создавая программу. Но как бывает в жизни, она бьёт, откуда не ждёшь.

            image

            Первый курс


            Обучение в таком заведении стандартное. Есть учебный план, есть преподаватели, которые обязаны следовать ему, сессия, курсовая, следующий курс. Первый курс нашего колледжа заключается в 10-11 классе с усиленной математикой и информатикой. Но уже на первом курсе я начал удивляться. На парах информатики нас заставляли писать, конспекты о клавиатуре. Заставляли делать лабораторные работы на тему «Регистрация почты в сервисе yandex». Подумал это первый курс, нормальное явление, не все такие умные, всем нужно получить азы пользования компьютера. И со спокойной душой перешёл на следующий курс.

            Второй курс


            Вот оно! Новые предметы, преподаватели, высшая математика и менеджмент. Первые недели все было не плохо, а дальше всё превратилось в полную ахинею. Математику нам преподавали в виде: «Вот формулы производных, сюда, туда, ответ». Хорошо, решать я их научился, а зачем они мне нужны, не объяснили. Каждая новая страница учебника именно так и преподносилась. Как можно заинтересовать студентов новой темой, просто преподнося новые формулы для новых примеров? Иногда путаешься, чем они отличаются от предыдущих, если бы учитель показал применение производных в жизни и показал их важность, было бы намного интересней изучать материал, да и отложилось бы на долгое время.

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

            Третий курс


            Кончилась математика, добавились другие профильные предметы. Теория осталась прежней, лабораторные работы по html и basic весь ГОД. Конспектировали о периферийных устройствах или про текстовый процессор блокнот. Согласитесь, наверное, не ожидаешь на предпоследнем курсе, что тебя будут учить печатать в блокноте.

            Появился интересный предмет «Сопровождение программного обеспечения». На нём, мы проходили 1С. Ура! Что-то нужное. Как я ошибался, ведь нам просто скинули на компьютеры инструкцию с примерами и сказали выполнить за целый год. Мало того, что инструкция не подходит по версии программы, так преподаватели сами не понимали программу. В итоге целый год вводили данные в 1С.

            image

            Была и база данных Access. Тут могу сказать спасибо, преподаватель попался хороший. Рассказывал, показывал и советовал. Было видно, что с тобой разговаривает специалист.

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

            Что я хочу этим сказать?


            Сейчас я нахожусь на последнем курсе моего учебного заведения. Все осталось прежним, разве что добавился Lazarus и написание дипломной работы. Я хочу сказать, что меня ничему не научили. Всё чему я научился — последствие психов, от того что меня ничему не учат. От такого и правда появляется мотивация к самообразованию. Хоть спасибо есть за что сказать.

            Не хочу ругать преподавателей, хотя из моих восьми преподавателей по информатике, нашлось только двое хороших. Я горю желанием обругать устаревшую систему образования и процесс прохождение аккредитации учебных заведений. Ведь в июле этого года я получу диплом, где гордо будет написано «Программист». Круто! Как вам программист 2018 года? Я умею регистрировать почту и печать в блокноте!

            image

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

            Люди предлагают поступить в ВУЗ, а то, мол, учишься в захолустье. Я давно интересуюсь поступлением в университет, но с каждой новой прочитанной статьёй, комментарием и отзывом своих друзей, желание отпадает.

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

            Не стоит искать образование в колледжах. Тут Вы найдёте основы основ. Женщин лет 50, которые преподают предмет «Архитектура ЭВМ» и с ней Вы будете составлять кроссворд в excel. А на другом предмете, вы будете писать электронную тетрадь в word, где нужно вставить из интернета определение информатики. Если откажитесь писать определение информатики на компьютере — заставят писать в тетрадке.

            Что мне делать дальше?


            Сейчас после окончания, меня отправят служить родине. После службы наступает момент выбора дальнейшего пути ниндзя. Пойти работать верстальщиком, уйти в фриланс? А может поступить в ВУЗ?

            Ради корочки идти в университет не особо хочу. Надеюсь, если меня всё-таки занесёт попутным ветром в высшее учебное заведение, я смогу найти там новые знакомства, хороших преподавателей и получить хорошие знания. Уже пора смириться, что даже после окончания университета, без самостоятельного обучения не стать IT-специалистом.

            Вы скажете мне, что вот, мол, ты в ПТУ деревенский поступил и жалуешься. Я отвечу, что Вы абсолютно правы, но только в том случае, если бы в университетах не происходило примерно то же самое.
            Original source: habrahabr.ru (comments, light).

            https://habrahabr.ru/post/339022/


            Метки:  

            [Перевод] Как создавали систему чувств ИИ в Thief: The Dark Project

            Суббота, 30 Сентября 2017 г. 11:20 + в цитатник

            Метки:  

            Security Week 39: Вечер восхитительных историй о том, как бизнесу наплевать на безопасность

            Суббота, 30 Сентября 2017 г. 10:33 + в цитатник
            Kaspersky_Lab сегодня в 10:33 Разработка

            Security Week 39: Вечер восхитительных историй о том, как бизнесу наплевать на безопасность

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

              Едва успела выйти новая версия MacOS (недели не прошло), как исследователь из Synack Патрик Уордл опубликовал шикарный пост о High Sierra. Оказывается, что Keychain – защищенный контейнер для учетных данных, PIN-кодов, номеров банковских карт и прочих важных данных – на самом деле уже версии три как ничего не защищает. То есть по факту Keychain это такое место, откуда можно разом украсть вот это вот все.

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

              Сразу после публикации Патрику насовали комментов в духе «что ж ты такой гад, не в Apple сообщил, а в блоге публикуешь», и что ему просто не хватает внимания окружающих. Но бедняга на самом деле сообщил в контору, и даже эксплойт готовый послал, просто контора от него отмахнулась! Мотивировали знатно – мол, нечего ставить софт из безнадежных источников, а ставьте только из MacAppStore, и читайте предупреждения безопасности от macOS. То есть в принципе это шаблонный ответ для сообщения обо всех локально-эксплуатируемых уязвимостях. Кто ставит левый софт – тот сам виноват. Кстати, программа вознаграждения за уязвимости в продуктах Apple не распространяется на MacOS.

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

              По словам исследователя, он протестировал уязвимость на версиях High Sierra и Sierra, и не видит причин, почему бы ей не быть и на El Capitan. Защититься от этого можно ценой небольшой толики удобства – достаточно установить блокировку Keychain, чтобы при попытке доступа к нему запрашивался пароль. Ну и да, по возможности избегайте установки приложения из левых источников.

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

              Новость. Исследование. Слова «инвестор» и «трейдер» даже звучат как-то богато. На мелочи эти ребята не размениваются, чтобы хоть чего-то добиться на бирже, нужны серьезные деньги. Но обстановка на фондом рынке меняется так быстро, что им необходима возможность заключать сделки в любое время, в любом месте. То есть через мобильник.

              Соответственно, мобильных приложений для трейдинга выпущено очень много. Понятно, что их вендоры должны тщательно выстраивать систему безопасности, даже в ущерб удобству – деньги на кону большие. Но вот на поверку все оказалось не так. Исследователи из IOActive взяли 21 приложение из топа (как для iOS, так и для Android) и нашли там много веселых дыр. Очень много. Вплоть до хранения паролей открытым текстом и передачи данных по HTTP.

              И в этот раз исследователи продемонстрировали ответственный подход к раскрытию уязвимостей и обратились к 13 брокерским компаниям, поставляющим эти приложения. Таки что бы вы думали? Ответили только две. Им некогда – торговать надо, а тут пристают с уязвимостями. Алехандро Эрнандез из IOActive вот так выразил свою реакцию на произошедшее: «Господа, я кажется, фрустрирован! Я работал аудитором и знаю, как жестко регулируется финансовый сектор. И очень странно, что мы столкнулись с такими проблемами».

              Deloitte уверяет, что кибератака затронула лишь несколько клиентов

              Новость. «Большая четверка» аудиторов всегда считалась примером оптимальных бизнес-практик и политик. Понятно, что в кибербезопасности трудно подстелить солому везде, где есть вероятность упасть, но и в этой области есть правила, которые не стоит нарушать, если не хочешь подставить своих клиентов. И вот на тебе! Отличился Deloitte, один из столпов бизнес-сообщества.

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

              Утечка почты Deloitte по своим последствиям может быть катастрофической, ведь компания, проводя аудит, имеет дело с секретнейшими бизнес-данными клиентов. Однако реакция самой Deloitte обескураживает: компания уверяет, что атака никак не повлияла на бизнес клиентов. И вообще, «кибербезопасность в компании обеспечивается на высочайшем уровне». Звучит как плохая шутка, учитывая, что их почту полгода читал неизвестно кто, а они этого и не замечали.

              Древности


              «ZipEater-1984»

              Использует «стелс»-функцию при вызове функций DOS FindFirst и FindNext. Очень опасен – иногда уничтожает файлы, у которых сумма символов расширения имени (т.е., например, у .COM-файлов: ‘C’ + ‘O’ + ‘M’) в ASCII-кодировке равна 100h, D6h, F3h, E2h или DFh. К таким файлам относятся .TXT, .STY, .BAS, .DOC,. ZIP, .EXE и .COM-файлы.

              Цитата по книге «Компьютерные вирусы в MS-DOS» Евгения Касперского. 1992 год. Страницa 36.

              Disclaimer: Данная колонка отражает лишь частное мнение ее автора. Оно может совпадать с позицией компании «Лаборатория Касперского», а может и не совпадать. Тут уж как повезет.
              Original source: habrahabr.ru (comments, light).

              https://habrahabr.ru/post/339020/


              Метки:  

              [Перевод] «Тюльпаномания»: биржевой пузырь, которого не было

              Суббота, 30 Сентября 2017 г. 10:17 + в цитатник
              itinvest сегодня в 10:17 Разное

              «Тюльпаномания»: биржевой пузырь, которого не было

              • Перевод


              Изображение: Wikimedia commons

              Научное издание Smithsonian опубликовало материал о том, что «тюльпаннную лихорадку», которую принято считать первым биржевым пузырём, выдумали голландские кальвинисты. Люди гнались за прибылью, но не настолько массово, как это описывается в учебниках и художественных произведениях. И эта гонка уж точно не вызвала крах экономики и промышленности. Мы подготовили русскоязычную адаптацию этой статьи.

              Всеобщее безумие


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



              Динамика индекса фьючерсных (зелёным) и опционных (красным) цен на луковицы в 1635—1637 годы по Томпсону. Изображение: Wikimedia Commons

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

              Есть только небольшой нюанс: эта история — неправда.

              Чтобы понять правду, нужно разобраться в истории


              Что же происходило на самом деле и как получилось, что история спекуляции тюльпанов в Голландии была настолько искажена? Энн Голдгар, профессор ранней современной истории Королевского колледжа Лондона, обнаружила правду, когда изучала архивы, для создания книги «Тюльпаномания: Деньги, честь и знания в Голландии Золотого Века».

              «Я всегда шучу, что книга должна называться «Тюльпаномания: это скучнее, чем вы думаете», — говорит Голдгар, — людям нравится эта легенда, так как они думают, что могут извлечь из неё урок. Я считаю это мнение ошибочным».

              Прежде чем ставить «тюльпанную лихорадку» в один ряд с пузырём Южного Моря, который случился в 1700-х годах в Англии, с железнодорожным пузырём XIX века, с пузырями доткомов и биткойнов, стоит изучить несколько доводов профессора Голдгара и понять, что происходило в голландском обществе на рубеже XVII века.

              Стоит начать с того, что страна пережила крупный демографический сдвиг, во время войны за независимость с Испанией. В этот период купцы прибыли в крупные портовые города: Амстердам, Гарлем, Делфт и начали торговлю, в том числе знаменитую Голландскую Ост-Индийскую компанию. Это принесло огромный доход Голландии, даже несмотря на военное положение в стране. Во главе новой независимой нации стала городская олигархия, состоящая из богатых купцов, в отличие от других европейских стран той эпохи, которые контролировались дворянством. В результате новые лица, идеи и деньги помогли революционизировать голландскую экономику в конце 16 века.

              Так как экономика изменилась, изменились социальные взаимодействия и культурные ценности. Растущий интерес к естественной истории и любовь к экзотике среди купечества вызвали рост цен на товары с востока, в том числе из Османской империи. Людям всех социальных классов пришлось развиваться в новых направлениях, которые появились с притоком новых товаров. Например, рыбный аукционер создал рукопись «Книга Китов» и эта работа позволила ему встретиться с президентом Голландии. Голландский ботаник Клузиус создал ботанический сад в Лейденском университете в 1590 году и тюльпан быстро поднялся на почётном месте.

              «Дикорастущие тюльпаны, найденные в долинах Тянь-Шаня, начали разводить в Стамбуле в 1055 году, а в XV веке они уже стали символами османов. Например, у султана Мехмеда II было 12 садов с тюльпанами, на содержание которых требовалось 920 садоводов» — пишет в книге «Тюльпаны» Анна Паворд, корреспондент по садоводству интернет-издания The Independent.

              Голландцы вывели, что тюльпаны могут быть выращены из семян и отростков материнской луковицы. Чтобы из семечки выросла луковица и цветок зацвёл, требуется от 7 до 12 лет. А уже созревшая луковица может стать тюльпаном через год. Особый интерес для ботаника Клузиуса и «тюльпановых спекулянтов» представляли «разбитые луковицы». Лепестки у тюльпанов, которые вырастали из этих луковиц, были не однотонными, а разноцветными. Предугадать, как будет выглядеть будущий цветок было невозможно. Натуралисты придумывали способы, как воспроизвести такие луковицы и бутоны, так как спрос на этот редкий вид постоянно рос. Как выяснилось позже, такой эффект получался из-за того, что луковицы болели. Они были хилыми и редко давали цветы.

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



              Печатный отчёт об итогах аукциона в Алкмаре 5 февраля 1637 года. Изображение: Wikimedia commons

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

              Начало легенды


              Вот, где миф вступает в игру. Согласно популярной легенде, «тюльпаномания» охватила все уровни голландского общества в 1630 году. «Стремление голландцами обладать редкими луковицами было настолько большим, что обычная промышленность была заброшена, а население, вплоть до самых низших слоёв, стало торговать тюльпанами» — пишет шотландский журналист Чарльз Маккей в популярной работе 1841 года «Чрезвычайно популярные заблуждения и безумие толпы». Согласно этой работе, все, от самых богатейших купцов, до беднейших трубочистов, скупали луковицы тюльпанов и перепродавали их по более высокой цене. Больше всего компаний по продаже тюльпанов было в конце 1636 года, а в феврале рынок начал трещать по швам. Всё больше и больше людей разорялись, в надежде купить заветные луковицы, и всё больше торговцев, оставшись в долгу, становились банкротами. По крайней мере, так всегда считалось.

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

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

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

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

              Кто распространил миф?


              Если «тюльпаномания» не была таким бедствием, зачем же её выставили в этом свете? Можно предположить, что в этом виноваты обиженные христианские моралисты. С большим богатством приходит волна социального беспокойства. «Невероятный уровень успеха вскружил им головы. Все невероятные истории, подтверждающие экономическую разруху: про моряка, брошенного в тюрьму и про трубочистов, пытающихся разбогатеть, пришли из пропагандистских брошюр. Их распространили голландские кальвинисты, боявшиеся, что тюльпановый бум приведёт к социальному гниению. Их убеждение, что это богатство было ужасным, дошло и до наших дней» — пишет историк Саймон Шам, в книге «Конфуз богатства: Интерпритация голландской культуры в Золотом Веке».

              «Некоторые идеи неискоренимы, например та, что Бог не любит хитрецов и насылает на них чуму. Вот что могли сказать люди в 1630 году, — говорит Энн Голдгар, — идея, что хитрость — грех дожила до современного общества. Гордыня предшествует падению».

              Голдгар не осуждает режиссёров и писателей, за неверную интерпретацию прошлого. Она недовольна неверными выводами историков и экономистов, которые те сделали в своих трудах, ещё больше распространив идею «тюльпаномании». «У меня не было никакой возможности узнать, что эта история — ложь, пока я не подняла старые архивы. Это было неожиданным сокровищем», — говорит Голдгар.

              Полезные ссылки и материалы для изучения фондового рынка


              Original source: habrahabr.ru (comments, light).

              https://habrahabr.ru/post/339018/


              Метки:  

              Интернет там, где его нет, или Стационарная связь на базе 3G-LTE

              Пятница, 29 Сентября 2017 г. 19:52 + в цитатник
              asterrios сегодня в 19:52 Администрирование

              Интернет там, где его нет, или Стационарная связь на базе 3G-LTE

                image


                Задумал я сделать интернет у себя на даче, в глуши. И наконец возможность срослась с желанием! Проблем в моей глуши две: дураки частые перебои с электроэнергией (в зависимости от погоды может ещё отключиться АТС) и плохая мобильная связь. Сигнал ловится не везде, а где ловится, там нестабилен. Добавляет сложности и оцинкованная крыша дома, экранирующая радиоволны. Возможности современного оборудования и корректировка запросов сужали и улучшали подходящие свойства, что привело меня к мысли создать максимально работоспособный узел сети. Я расскажу о том, как пытался поймать LTE-сигнал, с описанием оборудования и возможными проблемами.


                Подготовка и сбор информации о местности


                В моей глуши нормально ловится только МТС, в связи с чем был выбран именно этот оператор. Качество покрытия я определял с помощью https://4g-faq.ru/karty-pokrytiya/. На этой карте удобно выбирать режимы сети, а также хорошо видно ориентировочное расположение вышек стандартов 3G и LTE.


                Направление установки антенн выбиралось примерно так:



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



                Интересующие и важные характеристики


                Для начала необходимо понять, какой режим сети вас интересует. Диапазон частот у 3G и LTE разный, и, чтобы принимать их сигналы, необходимо выбрать антенны или облучатели, в зависимости от конфигурации, с соответствующей частотностью. Конечно, можно взять антенны с частотным диапазоном, который захватывает оба стандарта, но в таком случае выходной сигнал будет немного хуже (опять же, в зависимости от количества переходников, длины кабелей и их свойств; эти характеристики влияют на все конфигурации данной системы, в том числе это касается и затухания сигнала).


                Необходимо заранее проверить на площадке уровни сигналов мобильных сетей. Как уже говорил, я выбрал МТС, потому что здесь он ловится всегда и у МТС довольно много вышек (по сравнению с другими операторами) с разными режимами сетей, в том числе и LTE, который, надеюсь, в будущем проапгрейдят до 5G. Так что своё оборудование я подобрал «на вырост».


                Выбор и настройка оборудования


                Лишний раз переплачивать мне не хотелось. И система с легко заменяемыми компонентами выходила дешевле, чем спутниковый интернет и предложения от фирм, которые делают готовые наборы. Вариант со «свистком» отпал на первый день подбора оборудования: такая система крайне нестабильна. Ещё я планировал поставить систему на долгосрочную работу, но этот вариант тоже не подходил, поскольку компоненты корпуса при длительной работе перегревались и выводили «свисток» из строя до его остывания. В большинстве случаев данная проблема решалась пришаманенным кулером, но нестабильность подключения и потери пакетов не склонили меня к этому варианту. По той же причине я отказался от мысли о тандеме «свисток» + роутер (с поддержкой «свистка»).


                Изначально я планировал использовать «восьмёрку», она же антенна Харченко, но, учитывая зону покрытия и расстояние до ближайших населённых пунктов, есть возможность успешно ловить 3G-LTE на дистанциях, превышающих возможности «восьмёрки». Такой диапазон частот соответствует этим сетям и взят на случай непогоды, когда осадки существенно ухудшают качество сигнала. Меня удивил тот факт, что 4G-LTE работают в трёх диапазонах: около 800, около 1600 и около 2500.


                Частотные диапазоны LTE-сетей у различных провайдеров:



                Здесь разобраны частотные диапазоны 3G-сетей:



                Причины выбора канала относительно офсета


                Офсет, как мне кажется, гораздо лучше, так что я сделал неправильный выбор, особенно учитывая свои возможности: но LTE я ловил на «волнушку», и проблема заключается в высоте. Для начала я долго и усердно выбирал оборудование и возможные связки, в том числе и различные типы антенн. В итоге мне понравились два варианта:


                1. Офсетный рефлектор диаметром 0,9 м или более с облучателем на частотные диапазоны от 1700 до 2700 МГц и с поддержкой технологии MIMO.
                2. Сдвоенный волновой канал с такой же частотностью.

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


                На месте я выставлял антенну с помощью Google Maps и программы MDMA. Настольная версия MDMA позволяет проверить уровень сигнала на принимающем устройстве (модуль модема в роутере). С этой программой обращаться не так просто, но если вы разобрались с Netmonitor, то у вас она вряд ли вызовет затруднения. В конце концов, есть очень неплохие рекомендации и понятные инструкции. Обратите внимание, что нужно подключение через USB «папа-папа».


                Для проверки направления антенны достаточно собрать всю систему, то есть подключить антенну к роутеру, а роутер — к компьютеру, но только через USB-переходник. После чего запускаем MDMA и выбираем направление антенны.


                MDMA:



                Выбор конкретной модели роутера был обусловлен вышеперечисленными требованиями, но список был ограничен этими моделями:


                • Huawei E5172
                • Huawei B315S (есть альтернативы у провайдеров и операторов связи)
                • Skylink V-FL500
                • TP-LINK TL-MR6400
                • ZTE MF283 (есть альтернативы у провайдеров и операторов связи)
                • Huawei B310

                Разброс цен — от 4 до 9 тысяч рублей за единицу. Я выбрал Huawei B315S из-за дешевизны и возможности создания IP-телефонии и подключения до 32 устройств. А ещё он может ловить LTE.


                Конфигурация моего оборудования


                Роутер B315s-22:





                Huawei B315S изначально был привязан к Yota, но я выполнил отвязку


                Поскольку, кроме МТС, у меня ничего не ловилось, то и смысла усиливать то, что не ловится, не было. Но ситуация сложилась так, что мне пришлось купить роутер Yota, привязанный к сим-картам одноименного оператора (другие не подходили, проверял). Для отвязки каждого роутера свой способ, информацию легко найти в интернете, в том числе и на 4pda.ru. Полное название модели по классификации — Huawei LTE CPE B315s-22, так что, если вам необходимы технические характеристики, ищите по названию в интернете.


                Оборудование подключается почти так же, как и обычный роутер. Разница в том, что необходимо подключить внешние антенны, которые будут ловить сигнал. Чтобы у вас появился интернет, не требуется никакого стороннего ПО, но, как я уже указывал, оно необходимо для определения направления антенны. На рынке тысячи вариантов разъёмов и коннекторов, и вам нужны те, которые подходят непосредственно для вашего оборудования. В моем случае это коннекторы на кабелях SMA со стороны роутера и TS9 со стороны антенн. К счастью, оборудование я подобрал таким образом, что можно прямо из коробки провести первичную настройку и начать пользоваться интернетом. Никаких танцев с бубнами не потребовалось, только в настройках через веб-интерфейс поменял пароли и режим рабочего сигнала.


                Две антенны работают в тандеме по технологии MIMO, волновой канал с 24—28 dbi. Два кабеля с пониженными потерями длиной 10 метров, стандарт 5D-FB. Соответственно, придётся либо заказать переходники, либо заменить разъёмы подходящими, с одной стороны — для антенн, с другой — для подключения роутера.


                Результат трудов:



                Проблемы, с которыми я столкнулся (раздел о боли, унижениях и страданиях)


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


                1. Если собираетесь повторять такое далеко от городов-миллионников, то стоит заранее озаботиться покупкой оборудования в большом городе.
                2. Выбирайте тип и вид антенны в зависимости от ландшафта и расстояния до населённых пунктов.
                3. Обратите внимание на растительность, постройки и дистанцию между точками.
                4. Подбирайте оборудование, максимально подходящее под ваши требования.
                5. Не покупайте оборудование у оператора связи, если только не планируете пользоваться его услугами или не выигрываете сильно в цене.
                6. Используйте минимум переходников и оборудования на открытом воздухе.
                7. USB «папа-папа», он же USB AM — USB AM, пригодится на любой стадии работы или настройки, поэтому всегда держите его под рукой. Я в магазинах не нашёл, так что пришлось собирать на коленке из старых запчастей.
                8. Отвязка роутера от оператора — это боль. На некоторых роутерах и прошивках невозможно сделать отвязку без нарушения целостности корпуса, что приводит, в свою очередь, к потере гарантии. Ознакомьтесь с ассортиментом, всегда можно найти отвязанный вариант (или ваш выбор — AliExpress).
                9. Если всё-таки решились на привязанный, то озаботьтесь прошиванием в городе со стабильным интернетом. То есть подготовьте оборудование к работе до отъезда на площадку.
                10. Выбор тарифного плана и возможности безлимита. По большому счёту можно добиться безлимитного интернета через SIM-карту, однако для этого необходимо изменить конфигурацию модуля модема в роутере.
                11. Подготовьте подходящий модем-расходник для использования его IMEI, чтобы упростить себе задачу. Можно взять любой подходящий по конфигурации и поддерживаемым сетям.
                12. Если собираетесь использовать сети выше LTE, то подбирайте роутер с двумя антеннами. Это связано с поддержкой протокола MIMO.
                13. Проверяйте у магазинов рабочий диапазон частот выбранной вами антенны. Велика вероятность, что вас попробуют обмануть.

                Заключение


                Считаю, что я молодец: всё работает, скорости хватает на комфортный онлайн-просмотр фильмов. Ещё есть куда расти: на основе этой системы я планирую создать зачатки умного дома. Сейчас интернет ловится только на 3G, поэтому нужно кое-что доделать: увеличить высоту мачты, перепрошить модуль модема для возможности подключения безлимитного интернета, купить тариф для планшетов типа «Безлимитище» или аналог.


                Тем, кто пойдёт по моим стопам, рекомендую сразу брать безлимитный тариф, потому что у меня всего 30 Гб трафика. Сети 4G хоть и ловятся оборудованием, но очень плохо. Гипотез две: либо я не принял в расчёт рельеф, либо нашёл антенны, которые не подходят по диапазону рабочих частот. Полагаю, что виноваты антенны: продавец заявляет, что на них написан ошибочный частотный диапазон, но, скорее всего, это ложь, потому что сети 3G ловятся идеально, а именно их диапазон указан на антеннах.

                Original source: habrahabr.ru (comments, light).

                https://habrahabr.ru/post/338944/


                Метки:  

                Страницы 404

                Пятница, 29 Сентября 2017 г. 16:06 + в цитатник
                MagisterLudi сегодня в 16:06 Дизайн

                Страницы 404

                  image


                  404 страница. Это место для пасхалок, дурачества и креатива создателей сайтов. Про 404 ошибку есть даже выступление на TED.

                  Первая «4» — означает, что ошибка на стороне клиента, «04» — означает конкретную ошибку «Not Found». В компании EDISON Software философски считают, что пользователь не может ошибиться, что он всегда прав, если он на сайте компании.

                  Кому в пятницу нечего делать или кто в поисках вдохновения — добро пожаловать под кат, там подборка лучших (и худших) 404 страниц.



                  Начнем с самых животрепещущих сайтов, а потом перейдем к «попсовым».

                  Роскомнадзор


                  image

                  PornHub


                  image

                  Старая версия 404 Хабра


                  image

                  Новая версия 404 Хабра


                  image

                  Virgin.com


                  image

                  Google


                  image

                  YouTube


                  image

                  Facebook


                  image

                  Reddit.com


                  image

                  Amazon.com


                  image

                  Vk.com


                  image

                  Linkedin.com


                  image

                  Imgur.com


                  image

                  Aliexpress.com


                  image

                  Bing.com


                  image

                  Stackoverflow.com


                  image

                  Github.com


                  image

                  Dropbox.com


                  image

                  Craigslist.org


                  image

                  Dribbble.com


                  image

                  Awwwards.com


                  image

                  Csswinner.com


                  image

                  Coolhunting.com


                  image

                  Codyhouse.co


                  image

                  Mailchimp.com


                  image

                  Slack.com


                  image

                  Mashable.com


                  image

                  Bloomberg.com


                  image

                  Airbnb.com


                  image

                  Bitly.com


                  image

                  МГУ, психфак


                  image

                  Разговаривающая страница 404.

                  Еще подборки


                  404 pages from popular sites — Design Inspiration, Muzli, 2017

                  Anatomy of a 404 Error Page, Envato, 2016

                  Лучшие 404 страницы, Tproger, 2015

                  404 – страницы, ради которых стоит заблудиться на сайте, cossa, 2015

                  Идеальная страница 404 ошибки, или как удержать пользователя на сайте?, Habrahabr, 2014

                  Лучшие примеры 404 страницы, seo-design, 2013

                  Лучшие 404 страницы Рунета, oakhill, 2012

                  Лучшие примеры ошибки 404, netpeak, 2012

                  50 прикольных страниц ошибки 404 , Дежурка, 2009

                  image

                  image

                  image

                  image

                  image

                  Интерактивные



                  Играем в Pacman
                  image

                  Рушим сайт

                  Суслик

                  Спасаем леммингов

                  Поймай кота

                  P.S.


                  Ну и напоследок

                  image

                  А какая ваша любимая 404 страница?
                  Какая 404 страница на вашем сайте?
                  Original source: habrahabr.ru (comments, light).

                  https://habrahabr.ru/post/338994/


                  Метки:  

                  Чеклист: как выбрать модель системы управления правами доступа и не прогадать

                  Пятница, 29 Сентября 2017 г. 15:21 + в цитатник

                  Метки:  

                  [Перевод] Selenium и Node.js: пишем надёжные браузерные тесты

                  Пятница, 29 Сентября 2017 г. 14:21 + в цитатник
                  ru_vds сегодня в 14:21 Разработка

                  Selenium и Node.js: пишем надёжные браузерные тесты

                  • Перевод
                  Есть много хороших статей о том, как начать писать автоматизированные браузерные тесты, используя версию Selenium, предназначенную для Node.js.



                  В некоторых материалах говорится о том, как оборачивать тесты в Mocha или Jasmine, в некоторых всё автоматизируют с помощью npm, Grunt или Gulp. Во всех подобных публикациях можно найти сведения о том, как установить и настроить всё необходимое. Там же можно посмотреть простые примеры работающего кода. Всё это весьма полезно, так как, для новичка, собрать работающую среду тестирования, состоящую из множества компонентов, может оказаться не так уж и просто.

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

                  Сегодня мы начнём с того, на чём обычно заканчиваются другие материалы по автоматизации браузерных тестов с помощью Selenium для Node.js. А именно, мы расскажем о том, как повысить надёжность тестов и «отвязать» их от непредсказуемых явлений, которыми полны браузеры и веб-приложения.

                  Сон — это зло


                  Метод Selenium driver.sleep — худший враг разработчика тестов. Однако, несмотря на это, его используют повсюду. Возможно, это так из-за краткости документации для Node-версии Selenium, и из-за того, что она покрывает лишь синтаксис API. Ей недостаёт примеров из реальной жизни.

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

                  Для того, чтобы разобраться с особенностями метода driver.sleep, рассмотрим пример. Предположим, у нас есть анимированная панель, которая, в ходе появления на экране, меняет размеры и положение. Взглянем на неё.


                  Анимация панели

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


                  Замедленная анимация панели

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

                  Обычно эти анимации происходят так быстро, что у пользователя не возникает желания «ловить» меняющиеся кнопки. Люди просто ждут завершения анимации. Однако, это не относится к Selenium. Он настолько быстр, что может попытаться щёлкнуть по элементу, который всё ещё анимируется. Как результат — можно столкнуться с примерно таким сообщением об ошибке:

                  System.InvalidOperationException : Element is not clickable at point (326, 792.5)

                  В подобной ситуации многие программисты скажут: «Ага, мне нужно дождаться завершения анимации, поэтому просто использую driver.sleep(1000) для того, чтобы панель пришла в нормальное состояние». Похоже, задача решена? Однако, не всё так просто.

                  Проблемы driver.sleep


                  Команда driver.sleep(1000) выполняет именно то, чего от неё можно ожидать. Она останавливает выполнение теста на 1000 миллисекунд и позволяет браузеру продолжать работать: загружать страницы, размещать на них фрагменты документов, анимировать или плавно выводить на экран элементы, или делать что угодно другое.

                  Возвращаясь к нашему примеру, если предположить, что панель достигает нормального состояния за 800 миллисекунд, команда driver.sleep(1000) обычно помогает достичь того, ради чего её вызывают. Итак, почему бы ей не воспользоваться?

                  Главная причина заключается в том, что такое поведение недетерминированно. Тут имеется в виду то, что иногда такой код будет работать, а иногда — нет. Так как работает это не всегда, мы приходим к ненадёжным тестам, которые, при определённых условиях, дают сбои. Отсюда — дурная репутация автоматизированных браузерных тестов.

                  Почему же конструкции с driver.sleep не всегда работоспособны? Другими словами, почему это недетерминированный механизм?

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

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

                  Когда с веб-сайтом работает человек, он ждёт, пока элемент полностью появится, прежде чем по нему щёлкнуть. И когда появление элемента занимает меньше секунды, мы, вероятно, даже не заметим этого «ожидания». Selenium не только быстрее и требовательнее обычного пользователя. Тесты, в ходе работы со страницами, вынуждены сталкиваться с различными непредсказуемыми факторами. Рассмотрим некоторые из них:

                  1. Дизайнер может изменить время анимации с 800 миллисекунд на 1200 миллисекунд. В результате тест с driver.sleep(1000) даст сбой.
                  2. Браузеры не всегда делают именно то, что от них требуется. Из-за нагрузки на систему анимация может затормозиться и занять больше чем 800 миллисекунд. Возможно, даже больше, чем время ожидания, установленное на 1000 миллисекунд. Как результат — снова отказ теста.
                  3. Различные браузеры имеют различные механизмы визуализации данных, назначают разные приоритеты операциям по размещению элементов на экране. Добавьте новый браузер в набор программ для тестирования и тест опять вылетит с ошибкой.
                  4. Браузеры, которые контролируют страницы, JavaScript-вызовы, которые меняют их содержимое, по своей природе асинхронны. Если анимация в нашем примере применяется к блоку, который нуждается в информации с сервера, то перед запуском анимации придётся дождаться чего-то вроде результата AJAX-вызова. Теперь, кроме прочего, мы имеем дело с сетевыми задержками. Как результат, невозможно точно оценить время, необходимое для вывода панели на экран. Тест снова не сможет нормально работать.
                  5. Конечно, есть и другие причины для сбоев тестов, о которых я не знаю. Даже сами браузеры, без учёта внешних факторов — сложные системы, в которых, к тому же есть ошибки. Разные ошибки в разных браузерах. В результате, пытаясь писать надёжные тесты, мы стремимся к тому, чтобы они работали в разных браузерах различных версий и в нескольких операционных системах различных выпусков. Недетерминированные тесты в подобных условиях рано или поздно дают сбои. Если учесть всё это — становится понятным, почему программисты отказываются от автоматизированных тестов и жалуются на то, как они ненадёжны.

                  Как поступит программист для того, чтобы исправить одну из вышеописанных проблем? Он начнёт искать источник сбоя, выяснит, что всё дело — во времени, которое занимает анимация и придёт к очевидному решению — увеличить время ожидания в вызове driver.sleep. Затем, полагаясь на удачу, программист будет надеяться, что это улучшение сработает во всех возможных сценариях тестирования, что оно поможет справиться с различными нагрузками на систему, сгладит отличия в системах визуализации различных браузеров, и так далее. Но перед нами всё ещё недетерминированный подход. Поэтому так поступать нельзя.

                  Если вы пока ещё не убедились в том, что driver.sleep — это, во многих ситуациях, вредная команда, подумайте вот о чём. Без driver.sleep тесты будут работать гораздо быстрее. Например, мы надеемся, что анимация из нашего примера займёт всего 800 миллисекунд. В реальном тестовом наборе подобное предположение приведёт к использованию чего-то вроде driver.sleep(2000), опять же, в надежде на то, что 2-х секунд хватит на то, чтобы анимация успешно завершилась, какими бы ни были дополнительные факторы, влияющие на браузер и страницу.

                  Это — более секунды, потерянной всего на один шаг автоматизированного теста. Если подобных шагов будет много, очень быстро набежит немало таких вот «запасных» секунд. Например, недавно переработанный тест для всего одной из наших веб-страниц, который занимал несколько минут из-за чрезмерного использования driver.sleep, теперь выполняется меньше пятнадцати секунд.

                  Предлагаю вашему вниманию конкретные примеры избавления от driver.sleep и преобразования тестов в надёжные, полностью детерминированные конструкции.

                  Пара слов о промисах


                  JavaScript-API для Selenium интенсивно использует промисы. При этом детали скрыты от программиста благодаря использованию встроенного менеджера промисов. Ожидается, что этот функционал уберут, поэтому в будущем вам либо придётся разбираться с тем, как самостоятельно объединять промисы в цепочки, либо с тем, как пользоваться новым механизмом JavaScript async/await.

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

                  Пишем тесты


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

                  Как насчёт элемента, который динамически добавляется на страницу и не существует сразу после того, как страница завершит загрузку?

                  Ожидание появления элемента в DOM


                  Следующий код не будет работать, если элемент с CSS id my-button был добавлен в DOM после загрузки страницы:

                  // Код инициализации Selenium опущен для ясности
                  // Загрузка страницы.
                  driver.get('https:/foobar.baz');
                  // Найти элемент.
                  const button = driver.findElement(By.id('my-button'));
                  button.click();

                  Метод driver.findElement ожидает, что элемент уже присутствует в DOM. Он выдаст ошибку, если элемент невозможно немедленно найти. В данном случае «немедленно», из-за вызова driver.get, означает: «после того, как завершится загрузка страницы».

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

                  Обратите внимание на то, что вышеописанный сценарий не всегда нежелателен. Сам по себе вызов driver.findElement может быть удобен, если вы уверены, что элемент уже имеется в DOM.

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

                  driver.get('https:/foobar.baz');
                  // Страница загружается, засыпаем на несколько секунд
                  driver.sleep(3000);
                  // Надеемся, что три секунды достаточно для того, чтобы по прошествии этого времени элемент можно было бы найти на странице.
                  const button = driver.findElement(By.id('my-button'));
                  button.click();

                  По причинам, упомянутым выше, такая конструкция может привести к отказу, и, вероятно, приведёт. Нам нужно разобраться с тем, как ждать появления элемента в DOM. Это довольно просто, подобное нередко встречается в примерах, которые можно найти в интернете. Воспользуемся хорошо документированным методом driver.wait для того, чтобы ожидать того момента, когда элемент появится в DOM, не более двадцати секунд.

                  const button = driver.wait(
                    until.elementLocated(By.id('my-button')), 
                    20000
                  );
                  button.click();

                  Такой подход сразу же даст нам кучу плюсов. Например, если элемент будет добавлен в DOM в течение одной секунды, метод driver.wait завершит работу за одну секунду. Он не будет ждать все двадцать секунд, которые ему отведены.

                  Из-за этого поведения мы можем задавать тайм-ауты с большим запасом, не беспокоясь о том, что они замедлят тесты. Такая модель поведения выгодно отличается от driver.sleep, который всегда будет ждать всё заданное время.

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

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

                  Ожидание появления элемента на экране


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

                  const button = driver.wait(
                    until.elementLocated(By.id('my-button')), 
                    20000
                  )
                  .then(element => {
                     return driver.wait(
                       until.elementIsVisible(element),
                       20000
                     );
                  });
                  button.click();

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

                  Если вы освоите вышеописанный подход, причин писать недетерминированный код для Selenium у вас возникнуть уже не должно. Однако, писать такой код просто далеко не всегда.

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

                  Описание собственных условий


                  Благодаря методу until JavaScript API для Selenium уже имеет некоторое количество вспомогательных методов, которые можно использовать с driver.wait. Кроме того, можно организовать ожидание до тех пор, пока элемент не будет больше существовать, ожидать появления элемента, содержащего конкретный текст, ожидать показа уведомления, или использовать много других условий.

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

                  В соответствии с документацией, методу driver.wait можно предоставить функцию, которая возвращает true или false.

                  Скажем, нам нужно дождаться, чтобы свойство opacity некоего элемента стало бы равным единице:

                  // Получить элемент.
                  const element = driver.wait(
                    until.elementLocated(By.id('some-id')),
                    20000
                  );
                  // driver.wait всего лишь нужна функция, которая возвращает true или false.
                  driver.wait(() => { 
                    return element.getCssValue('opacity')      
                      .then(opacity => opacity === '1');
                  });

                  Такая конструкция кажется полезной и подходящей для повторного использования, поэтому поместим её в функцию:

                  const waitForOpacity = function(element) {
                    return driver.wait(element => element.getCssValue('opacity')      
                      .then(opacity => opacity === '1');
                    );
                  };

                  Теперь воспользуемся этой функцией:

                  driver.wait(
                    until.elementLocated(By.id('some-id')),
                    20000
                  )
                  .then(waitForOpacity);

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

                  const element = driver.wait(
                    until.elementLocated(By.id('some-id')),
                    20000
                  )
                  .then(waitForOpacity);
                  // Вот незадача. Переменная element может быть true или false, это не элемент, у которого есть метод click().
                  element.click();

                  По той же причине мы не можем в подобной конструкции пользоваться объединением промисов в цепочки.

                  const element = driver.wait(
                    until.elementLocated(By.id('some-id')),
                    20000
                  )
                  .then(waitForOpacity)
                  .then(element => {
                    // Так тоже не пойдёт, element и здесь является логическим значением.
                    element.click();
                  }); 

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

                  const waitForOpacity = function(element) {
                    return driver.wait(element => element.getCssValue('opacity')      
                      .then(opacity => {
                        if (opacity === '1') {
                          return element;
                        } else {
                          return false;
                      });
                    );
                  };

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

                  Вот как можно это применить вместе с объединением промисов в цепочки:

                  driver.wait(
                    until.elementLocated(By.id('some-id')),
                    20000
                  )
                  .then(waitForOpacity)
                  .then(element => element.click());

                  Или даже так:

                  const element = driver.wait(
                    until.elementLocated(By.id('some-id')),
                    20000
                  )
                  .then(waitForOpacity);
                  element.click();

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

                  Уходим в минус


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

                  Предположим, элемент уже присутствует в DOM, но вы не должны с ним взаимодействовать до того, как некоторые данные будут загружены через AJAX. Элемент может быть перекрыт панелью с надписью «Загрузка...».

                  Если вы обратили пристальное внимание на условия, которые предлагает метод until, вы могли заметить методы вроде elementIsNotVisible или elementIsDisabled или на не столь очевидный метод stalenessOf.

                  Благодаря одному из этих методов можно организовать проверку на скрытие панели с индикатором загрузки:

                  // Элемент уже добавлен в DOM, отсюда сразу же произойдёт возврат.
                  const desiredElement = driver.wait(
                    until.elementLocated(By.id('some-id')),
                    20000
                  );
                  // Но с элементом нельзя взаимодействовать до тех пор, пока панель с индикатором загрузки
                  // не исчезнет.
                  driver.wait(
                    until.elementIsNotVisible(By.id('loading-panel')),
                    20000
                  );
                  // Панель с информацией о загрузке больше не видна, с элементом теперь можно взаимодействовать, не опасаясь ошибок.
                  desiredElement.click();

                  Исследуя вышеописанные методы, я обнаружил, что метод stalenessOf особенно полезен. Он ожидает, пока элемент не будет удалён из DOM, что, кроме прочих причин, может произойти из-за обновления страницы.

                  Вот пример ожидания обновления содержимого iframe для продолжения работы:

                  let iframeElem = driver.wait(
                    until.elementLocated(By.className('result-iframe')),
                    20000  
                  );
                  // Выполняем некое действие, которое приводит к обновлению iframe.
                  someElement.click();
                  // Ожидаем пока предыдущий iframe перестанет существовать:
                  driver.wait(
                    until.stalenessOf(iframeElem),
                    20000
                  );
                  // Переключаемся на новый iframe. 
                  driver.wait(
                    until.ableToSwitchToFrame(By.className('result-iframe')),
                    20000
                  );
                  // Всё, что будет написано здесь, относится уже к новому iframe.

                  Итоги


                  Главная рекомендация, которую можно дать тем, кто стремится писать надёжные тесты на Selenium, заключается в том, что всегда следует стремиться к детерминизму и отказаться от метода sleep. Полагаться на метод sleep — значит основываться на произвольных предположениях. А это, рано или поздно, приводит к сбоям.

                  Надеюсь, приведённые здесь примеры помогут вам продвинуться по пути создания качественных тестов на Selenium.

                  Уважаемые читатели! Используете ли вы Selenium для автоматизации тестов?
                  Original source: habrahabr.ru (comments, light).

                  https://habrahabr.ru/post/338984/


                  Метки:  

                  [Перевод] Что известно об атаке на цепи поставок CCleaner

                  Пятница, 29 Сентября 2017 г. 14:20 + в цитатник
                  Cloud4Y сегодня в 14:20 Администрирование

                  Что известно об атаке на цепи поставок CCleaner

                  • Перевод


                  Атаки на цепи поставок (supply-chain attacks) — очень эффективный способ распространения вредоносного программного обеспечения в целевые организации. Это связано с тем, что при атаках на цепи поставок злоумышленники пользуются доверительными отношениями между производителем/поставщиком и клиентом, чтобы атаковать организации и отдельных лиц по различным мотивам. Червь Petya/Nyetya/NePetya, который был выпущен в сеть в начале 2017 года, показал насколько масштабны эти типы атак. Часто, как и в случае с Petya, исходный вектор атаки может оставаться скрытым в течение некоторого времени.

                  Недавно исследователи Talos заметили случай, когда серверы загрузки, используемые компанией-разработчиком для распространения легитимного пакета программного обеспечения, были использованы для загрузки вредоносного ПО на компьютеры ничего неподозревающих жертв. В течение некоторого периода версия CCleaner 5.33, распространяемая Avast, содержала многоступенчатую вредоносную нагрузку. 5 миллионов новых пользователей загружают CCleaner в неделю. Учитывая потенциальный ущерб, который может быть вызван сетью зараженных компьютеров подобного размера, решено было действовать быстро. 13 сентября 2017 года Cisco Talos уведомила Avast. В следующих разделах будут обсуждаться конкретные детали, касающиеся этой атаки.

                  Технические подробности


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


                  Рисунок 1: Снимок экрана CCleaner 5.33

                  13 сентября 2017 года, проведя бета-тестирование клиентов новой технологией обнаружения эксплойтов, Cisco Talos обнаружила исполняемый файл, который определялся как вредоносная программа. Это был установщик CCleaner v5.33 с легитимных серверов загрузки CCleaner. Talos провёл первоначальный анализ, чтобы определить, что заставляет систему защиты блокировать CCleaner. Они определили, что, хотя загруженный исполняемый файл был подписан с использованием действительной цифровой подписи Piriform, CCleaner не был единственным приложением, которое было загружено. Во время установки CCleaner 5.33 32-разрядный двоичный файл CCleaner, также содержал вредоносную нагрузку с возможностью использовать алгоритм генерации домена (DGA), а также функции выдачи команд и управления (Command and Control — C2).

                  При просмотре страницы истории версий на сайте загрузки CCleaner выяснилось, что версия (5.33) была выпущена 15 августа 2017 года. 12 сентября 2017 года была выпущена версия 5.34. Версия, содержащая вредоносную нагрузку (5.33), распространялась между этими датами. Эта версия была подписана с использованием действительного сертификата, который был выпущен для компании Piriform Ltd, которую недавно приобрел Avast, компанией Symantec и действителен до 10.10.2018.


                  Рисунок 2: Цифровая подпись CCleaner 5.33

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

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

                  В двоичном коде CCleaner был найден следующий артефакт компиляции:
                  S:\workspace\ccleaner\branches\v5.33\bin\CCleaner\Release\CCleaner.pdb

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

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

                  Процесс установки вируса


                  '__scrt_get_dyn_tls_init_callback' был изменен для запуска кода CC_InfectionBase (0x0040102C) с целью перенаправления потока выполнения кода на вредоносный до продолжения обычных операций CCleaner. Вызываемый код отвечает за дешифрование данных, которые содержат два уровня вредоносной нагрузки: загрузчик PIC (позиционно-независимого программного кода) и DLL-файл.

                  Используя HeapCreate (HEAP_CREATE_ENABLE_EXECUTE, 0,0), создаётся исполняемая куча. Содержимое расшифрованных данных, содержащих вредоносное ПО, копируется в кучу, исходные данные стираются. Затем вызывается PE-загрузчик и начинается его работа. Как только процесс заражения начался, двоичный код стирает области памяти, в которых ранее содержался PE-загрузчик и DLL-файл, освобождает ранее выделенную память, уничтожает кучу и продолжает исполняться с обычными операциями CCleaner.

                  PE-загрузчик использует методы позиционно-независимого кодирования, чтобы найти DLL-файл в памяти. Затем он переносит DLL в исполняемую память и вызывает DLLEntryPoint, чтобы начать его выполнение.

                  CCBkrdr_GetShellcodeFromC2AndCall отвечает за многие из вредоносных операций, обнаруженные Talos при анализе этого вредоносного ПО. Во-первых, он записывает текущее системное время. Затем он задерживает выполнение вредоносного кода на 601 секунду, вероятно, с целью уклониться от автоматизированных систем анализа, которые настроены на проверку ПО на вирусы в отладчике в течение предопределенного периода времени. Чтобы реализовать эту функцию задержки, вредоносное ПО вызывает функцию, которая пытается выполнить ping 224.0.0.0 с использованием таймаута delay_in_seconds, установленного на 601 секунду. Затем он определяет текущее системное время, чтобы узнать прошло ли 600 секунд. Если это условие не выполняется, вирус завершает выполнение, в то время как CCleaner продолжает выполняться. В ситуациях, когда вредоносное ПО не может выполнить IcmpCreateFile, оно возвращается к использованию функции Sleep () для реализации той же функции задержки. Вредоносная программа также сравнивает текущее системное время со значением, хранящимся в следующем разделе реестра:

                  HKLM \ SOFTWARE \ Piriform \ Agomo: TCID

                  Если время, хранящееся в TCID, ещё не пришло, вирус также прекратит выполнение.


                  Рисунок 3: Процедура задержки

                  Затем проверяются привилегии, назначенные пользователю. Если текущий пользователь, не является администратором, вредоносное ПО прекратит выполнение.


                  Рисунок 4: Проверка привилегий

                  Если у пользователя, запустившеего вредоносное ПО, есть права администратора, на зараженной системе активируется SeDebugPrivilege. Затем вредоносное ПО считывает значение «InstallID», которое хранится в следующем разделе реестра:

                  HKLM \ SOFTWARE \ Piriform \ Agomo: Muid

                  Если это значение не существует, вредоносное ПО создает его с помощью '((rand () * rand () ^ GetTickCount ())'.

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


                  Рисунок 5: Структура данных CCBkdr_System_Information

                  После сбора информации о системе она зашифровывается и кодируется с использованием модифицированного Base64. Затем вредоносное ПО устанавливает связь с командным сервером (C2), как описано в следующем разделе.

                  Command and Control (C2)


                  Как только ранее упомянутая системная информация была собрана и подготовлена для передачи на сервер C2, начинается попытка передать её с использованием запроса POST HTTPS на 216[.]126[.]225[.]148.

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


                  Рисунок 6: Структура данных CCBkdr_ShellCode_Payload

                  После установки вируса продолжаются обычные операции CCleaner. Ниже приведена диаграмма, описывающая работу этого вредоносного ПО на высоком уровне:


                  Рисунок 7: Схема процесса запуска вредоносной нагрузки

                  Алгоритм генерации домена


                  В ситуациях, когда основной сервер C2 не возвращает ответ на запрос HTTP POST, описанный в предыдущем разделе, вредоносная программа использует алгоритма DGA. В этом случае он основан на времени и может быть рассчитан с использованием значений текущего года и месяца. Ниже приведен список доменов DGA:


                  Рисунок 8: генерация доменов для 12 месяцев

                  Вредоносная программа будет инициировать DNS-поиск для каждого домена, генерируемого алгоритмом DGA. Если DNS-поиск не приведет к возврату IP-адреса, этот процесс будет продолжен. Вредоносная программа выполнит DNS-запрос активного DGA-домена и ожидает получить два IP-адреса с сервера доменных имен. Затем вредоносная программа вычислит вторичный сервер C2, выполнив серию битовых операций с полученными IP-адреса и объединив их для определения нового фактического адреса командного сервера. Диаграмма, показывающая этот процесс, приведена ниже:


                  Рисунок 9: Определение адреса командного сервера

                  Cisco Talos во время анализа определила, что DGA-домены не были заняты, поэтому они были зарегистрированы и заблокированы, чтобы злоумышленники не могли использовать их в своих целях.

                  Потенциальный ущерб


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


                  Рисунок 10: Статистика CCleaner

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

                  При анализе телеметрических данных Cisco Umbrella о доменах, связанных с этой атакой, Talos определил значительное количество систем, которые выполняли соответствующие DNS-запросы. Поскольку эти домены никогда не регистрировались, разумно сделать вывод о том, что единственной причиной является этот вирус. Только домены, относящиеся к августу и сентябрю (что коррелирует со временем, когда эта угроза была активна), показывают значительную активность.


                  Рисунок 11: Активность DGA домена за июль 2017 года

                  Как упоминалось ранее, версия CCleaner, которая включала это вредоносное ПО, была выпущена 15 августа 2017 года. Следующий график показывает значительное увеличение активности DNS, связанной с DGA-доменом, используемым в августе 2017 года:


                  Рисунок 12: Активность для домена в августе 2017 года


                  Рисунок 13: Активность для домена в сентябре 2017 года

                  После обращения к Avast было замечено, что C2 сервер, указанный по умолчанию, стал недоступным для зараженных систем. В результате мы увидели значительное увеличение количества запросов, направленных на DGA-домены.


                  Рисунок 14: Трафик после отключения сервера

                  Стоит также отметить, что на 18 сентября антивирусное обнаружение этой угрозы остается очень низким (1/64).


                  Рисунок 15: Проверка обнаружения вируса

                  Ещё причины для беспокойства


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

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


                  Рисунок 16

                  PHP скрипт сравнивает системные маяки полученные с заражённой машины по трём значениям: $DomainList, $IPList и $HostList. Это необходимо для определения того, должна ли зараженная система доставлять вредоносную нагрузку Stage 2. Ниже приведен сжатый PHP-код, который демонстрирует это:


                  Рисунок 17

                  База данных C2 содержала две таблицы: одну, описывающую все машины, которые «общались» с сервером, и описание всех машин, получивших загрузку Stage 2. Причем обе из них были датированы с 12 сентября по 16 сентября. За этот период времени на сервер C2 было отправлено более 700 000 машин, и более 20 машин получили Stage 2 нагрузку. Важно понимать, что целевой список может быть изменён и был изменён в течение периода, когда сервер был активен для заражения целевых организаций.

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

                  Основные данные подключения хранятся в таблице «Сервер». Вот пример для одного из узлов Talos в этой таблице базы данных:


                  Рисунок 18

                  А также список установленных программ.


                  Рисунок 19

                  И список процессов.


                  Рисунок 20

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


                  Рисунок 21

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


                  Рисунок 22

                  На следующем снимке экрана показано количество затронутых правительственных систем по всему миру.


                  Рисунок 23

                  Уязвимые системы с доменом, содержащим слово «банк»:


                  Рисунок 24

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

                  CODE REUSE


                  Talos рассмотрел заявления от исследователей Лаборатории Касперского о совпадении кода с образцами вредоносных программ, которые, как известно, используются Group 72. Хотя это никоим образом не является доказательством, мы можем подтвердить совпадение и согласны с тем, что это важная информация.

                  Слева: 2bc2dee73f9f854fe1e0e409e1257369d9c0a1081cf5fb503264aa1bfe8aa06f (CCBkdr.dll)

                  Справа: 0375b4216334c85a4b29441a3d37e61d7797c2e1cb94b14cf6292449fb25c7b2 (Missl backdoor — APT17 / Group 72)


                  Рисунок 25

                  ВЫВОД


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

                  Ниже приведены индикаторы компроментации, связанные с этой атакой.

                  File Hashes
                  6f7840c77f99049d788155c1351e1560b62b8ad18ad0e9adda8218b9f432f0a9
                  1a4a5123d7b2c534cb3e3168f7032cf9ebf38b9a2a97226d0fdb7933cf6030ff
                  36b36ee9515e0a60629d2c722b006b33e543dce1c8c2611053e0651a0bfdb2e9

                  DGA Domains
                  ab6d54340c1a[.]com
                  aba9a949bc1d[.]com
                  ab2da3d400c20[.]com
                  ab3520430c23[.]com
                  ab1c403220c27[.]com
                  ab1abad1d0c2a[.]com
                  ab8cee60c2d[.]com
                  ab1145b758c30[.]com
                  ab890e964c34[.]com
                  ab3d685a0c37[.]com
                  ab70a139cc3a[.]com

                  IP Addresses
                  216[.]126[.]225[.]148

                  Installer on the CC: dc9b5e8aa6ec86db8af0a7aa897ca61db3e5f3d2e0942e319074db1aaccfdc83 (GeeSetup_x86.dll)

                  64-bit trojanized binary
                  128aca58be325174f0220bd7ca6030e4e206b4378796e82da460055733bb6f4f (EFACli64.dll)

                  32-bit trojanized binary: 07fb252d2e853a9b1b32f30ede411f2efbb9f01e4a7782db5eacf3f55cf34902 (TSMSISrv.dll)

                  DLL in registry: f0d1f88c59a005312faad902528d60acbf9cd5a7b36093db8ca811f763e1292a

                  Registry Keys:
                  HKLM\Software\Microsoft\Windows NT\CurrentVersion\WbemPerf\001
                  HKLM\Software\Microsoft\Windows NT\CurrentVersion\WbemPerf\002
                  HKLM\Software\Microsoft\Windows NT\CurrentVersion\WbemPerf\003
                  HKLM\Software\Microsoft\Windows NT\CurrentVersion\WbemPerf\004
                  HKLM\Software\Microsoft\Windows NT\CurrentVersion\WbemPerf\HBP
                  Original source: habrahabr.ru (comments, light).

                  https://habrahabr.ru/post/338980/


                  Метки:  

                  Больше сюрпризов от Apple: обновленные правила размещения на App Store

                  Пятница, 29 Сентября 2017 г. 14:08 + в цитатник
                  nanton сегодня в 14:08 Разработка

                  Больше сюрпризов от Apple: обновленные правила размещения на App Store

                    Для разработчиков на iOS настала эпоха перемен: новые девайсы, новые инструменты, новые требования маркета. О технических особенностях обновленной платформы и о том, как следует оформлять и продвигать свое детище на новой версии App Store, было сказано уже немало. Сегодня мы хотим обратиться к еще одной перемене, которая обсуждается сейчас менее широко — изменениям в правилах публикации.



                    В последние месяцы Apple корректировали и дополняли список официальных требований к продуктам, размещаемым на сторе уже дважды. Первая порция правок пришлась на июнь, как заблаговременная подготовка почвы для осеннего релиза; вторая была опубликована совсем недавно. За каждой следовала массовая зачистка — удаление тысяч приложений с маркета без предупреждений и надежды на амнистию. Раз уж все так серьезно, пожалуй, стоит поподробнее разобрать, что именно изменилось и стоит ли уже начинать бояться. Мы изучили июньское и сентябрьское соглашения и собрали все значительные нововведения здесь, под катом.

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

                    Итак, начнем с июньских тезисов. Что здесь нужно знать?

                    1. Удаляться без разговоров и предупреждений будут:

                    • Приложения для купли-продажи контролируемых веществ (за исключением официальных приложений аптечных сетей).
                    • Устаревшие приложения, для которых разработчики больше не обеспечивают поддержку, что приводит к некорректной работе.
                    • Приложения, созданные на базе шаблонов, при помощи специальных сервисов типа «собери сам без знания кода».
                    • Приложения, использующие технологии, фреймворки и функции, несовместимые с новыми версиями OS.
                    • Приложения для торговли бинарными опционами.

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

                    3. То же относится и к музыкальным приложениям, которые получают доступ к пользовательским данным в Apple Music.

                    4. Медицинские приложения также будут подвергаться более жесткому контролю. В описании должна раскрываться методология, которая используется для медицинских заключений и гарантирует их точность. Сразу будут отклоняться продукты, которые якобы производят операции, требующие специального оборудования (измеряют давление, температуру, уровень сахара в крови, делают рентген). Обязательно включение рекомендации обратиться к специалисту для более точной консультации.

                    5. Продолжительность периода подписки не может составлять менее недели; подписка должна быть актуальна на всех девайсах пользователя.

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

                    7. Допускается использование кода «со стороны», при условии, что оно осуществляется через WebKit или JavaScript Core, а разработчик состоит в Apple Development Program.

                    8. В текст добавлены мелкие изменения, касающиеся разных аспектов оформления:

                    • Названия: не должны включать выражения типа «for children», «for kids», если не принадлежат к соответствующей категории, а также отсылки к цене.
                    • В сабтайтлах запрещено: ссылаться на другие приложения или давать информацию о продукте, которую не можете подтвердить.
                    • Иконки: допускается использование кастомизированных иконок, при условии что остается возможность вернуться к исходной. Вариации иконок должны быть связаны с контентом приложения (например, иконки, отображающие разные типы погоды для утилиты с прогнозами) и синхронизироваться по всей системе.

                    Теперь перейдем к самой свежей, сентябрьской версии. Здесь список правок полаконичнее и во многом тематически перекликается с и продолжает то, что было намечено летом:

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

                    2. Аутентификация через Face ID должна осуществляться только и исключительно при помощи LocalAuthentication (использовать ARKit и прочие технологии запрещено). Для пользователей младше 13 лет следует предоставить альтернативный метод аутентификации.

                    3. ARKit допустимо применять только в том случае, если вы планируете подарить пользователям «богатый, интегрированный опыт взаимодействия с дополненной реальностью». Иными словами, парой моделей или анимаций тут не обойтись.

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

                    5. Продукты, в которых используются технологии типа ARKit, Camera API, Photo API для распознавания лиц, обязательно должны иметь пользовательское соглашение и запрашивать согласие на сбор данных. Полученную информацию нельзя использовать для целей, не оговоренных в соглашении.

                    6. Дискриминация по этническому признаку (наряду с полом, сексуальностью и религией) теперь тоже будет попадать под санкции.

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

                    Если обобщить, изменения касаются прежде всего безопасности данных и некоторых этических моментов. Конечно, в зоне риска в первую очередь те, кто совсем потерял совесть, однако с таким обилием требований к сбору данных многие приложения могут не пройти модерацию. Кроме того, Apple очерчивает границы для свежеиспеченных технологий и также понемногу начинает закручивать гайки в отношении инструментария. В первую очередь имеет смысл пристально отслеживать будущие обновления текста тем, кто работает с ARKit, Face ID и прочими новинками — они, как видно из всего сказанного, сейчас на стадии активной кодификации.

                    Удачи и долгой жизни на маркете!
                    Original source: habrahabr.ru (comments, light).

                    https://habrahabr.ru/post/338982/


                    Метки:  

                    Поиск сообщений в rss_rss_hh_full
                    Страницы: 1824 ... 1553 1552 [1551] 1550 1549 ..
                    .. 1 Календарь