Как я искал идею для первого проекта на Arduino или Wake-on-LAN на Arduino



Предыстория


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

С чего начать?


Наверное, самый частый вопрос, когда начинаешь новое дело — это «с чего начать?» Делать что-то ненужное не хотелось, а что-то очень сложное могло привести к тому, что не разобравшись в деталях мог охладеть к проекту, не осилив его. Тут я вспомнил про одну особенность своего PC, которая доставляла мне достаточно неудобств. В силу определенных обстоятельств мне частенько приходится подключаться к домашнему компьютеру. Естественно, для того чтобы подключиться по RDP, компьютер должен быть включен. Исходя из этого было два варианта: 1) оставлять PC включенным (что по меньшей мере неудобно); 2) пробуждать его перед подключением.

Очевидно, что второе решение более лаконичное как экономически так и практически. Любые попытки заставить стабильно работать wake-on-lan заканчивались тем, что компьютер становился недоступным, так как не выходил из сна. А если быть точнее, он мог был быть пробужден в пределах какого-то ограниченного времени (около 15-30 минут) после отправления в сон. За рамками этого временного интервала разбудить не удавалось. Пробовались разные платы и разные пляски с бубном вокруг биоса. Результат был всегда одинаков. Я допускаю мысль, что все же это возможно при данных условиях на данном железе, но временные затраты на решение задачи были слишком большими. В итоге при очередной «командировке» приходилось оставлять включенный компьютер без присмотра на несколько дней. Я думаю, большинству понятно, что нельзя сказать, что задача удаленного доступа была решена. Учитывая, что все, что требуется при физическом контакте для пробуждения — это короткое нажатие на кнопку (простое замыкание контактов), я решил, что это достаточно простой проект, да и весьма полезный для меня.

Сказано — сделано


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

Набор так же достаточно простой: Arduino nano, ethernet MINI ENC28J60, провода для подключения контактов и 1 транзистор (изначально думал обойдусь без транзистора, просто подав такое же напряжение как на первом контакте на второй контакт, но эмпирически установил, что плата ждет не появления эквивалентного напряжения на втором контакте, а просто замыкание на землю первого).

Питание берется с USB, а проверка на включение снимается со свободного пина для кулера на материнской плате.

imageimage

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

Работает все примерно так: инициируются Mac-адрес, IP, маска подсети, порт и размер буфера. Дальше инициализация платы ENC28J60 и ethernet/ip. Потом в цикле проверяется буфер, не пришло ли что-нибудь запросом. Интересующие нас запрос — это запрашиваемая методом GET страница c адресом на который мы будем реагировать. В случае если получаем запрос на корневую страницу («GET / HTTP...») даем ответ «It works!» имитируя Apache. В заголовках так же всячески имитируем Apache(Server:«Apache/2.4.9 (Win32)», все такое), чтобы Вася, начитавшийся журнала «Хакер», пытался понять, почему же у него не получается сломать сервер. В случае, если запрос идет не к корневой странице, то если запрашиваемая страница не является той, что мы определили для включения/выключения выдаем «404 Not Found».

По подключения все так же не сложно. Рисовать схему смысла не вижу. Так как по сути подключаются между собой 3 платы (Arduino nano, ENC28J60, материнская плата) и 1 транзистор. Я решил, что для тех, кто не силен в схемотехнике, нагляднее будет представить просто таблицу на пересечении колонок, в которой будет подключение.

Arduino nano ENC28J60 материнская плата транзистор
+5 +5USB
D13 SCR
3v3 VIN
GND GND
D2 INT
D12 SO
D11 ST
D10 CS
D8 CPU_fan
D6 база
GND эмиттер
Power SW коллектор
GND GND


image

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

image

При работе после получения запроса на включение/выключение программа смотрит, есть ли напряжение на «CPU_fan», исходя из этого решает, нужно ли подавать питание на транзистор. Если нужно — подает на базу транзистора ток и через время отключает обратно. Ток на базе транзистора позволяет ему открыться и замкнуть контакты «Power SW» и «GND».

Цель достигнута. Более того, получил возможность вывести PC после BSOD'а, так как можем послать сигнал, который будет эмулировать 4 секундное нажатие на кнопку питания.

Заключение


Это далеко не самое сложное из того, что делалось. Были и свои, более сложные проекты, и написание кода «в помощь» другим людям, но, во-первых, для первой статьи хотелось выбрать не сложный «проект» (слишком громкое слово для вышеописанного), отвечающий «песочнице», во-вторых, первый проект — он как первая любовь. Западает в душу. Тем самым хотелось бы попытаться замотивировать, показать, что первый шаг может быть проще, чем кажется. И если хотя бы один человек после прочтения попробует, буду считать, что статья удалась. Самым «маленьким» советую начать с видео от Jeremy Blum.

P.S.: Ждем с коллегой посылки для сборки квадрокоптера и уже подумываем собрать хексопад. А стоило-то лишь попробовать…

Ссылка на скейтч и библиотеку по работе с ENC28J60.
Поделиться публикацией

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

    0
    А транзистор правда без резистора в базе использован?
    Питание лучше брать с джампера переключателя питания USB-портов, там есть Vsb — +5В дежурного питания которые есть всегда и просто +5v — тут 5 вольт есть только когда компьютер включен.
      0
      Питание есть всегда, пока есть напряжение на материнской плате.
      На 1 картинке после фразы «Питание берется с USB, а проверка...» видно куда подключаются земли (2 коричневых провода) и откуда снимается + 5V (красный провод — его плохо видно он за двумя коричневыми).
      Наверное «по феншую» нужен резистор, но полгода после того как последний раз перебрал работает без нареканий.
        +1
        Ну я и говорю, что лучше подключаться не к USB разъему, там очень легко попутать контакты. И похоже что питание USB у вас стоит в положении «питание от дежурного источника».
        Вообще-то резистор там не просто нужен а ОБЯЗАТЕЛЕН. ничего не замечаете только потому что перегрузка достаточно кратковременна — всего 1-2 секунды за сколько то там дней насилуется транзистор, выход ардуины и стабилизатор питания на плате ардуины. В любой момент времени один из компонентов может не выдержать и потянуть за собой остальное. Найдите все-таки резистор, выпаять можно даже где-то на любой номинал — от 500 Ом до 100 кОм. Можно даже SMD-шный.
          0
          Хорошо, спасибо за совет. Как полезу внутрь — поставлю.
      0
      А можно немного инфы про доступ из интернета? На роутере настроено динамическое доменное имя, проброс порта и тд?
        0
        А может, у него белый IP? <зависть>
          +1
          Тогда, выходит, как минимум, два :)
        0
        Настроен проброс порта. По статическому IP на определенный порт имеем доступ к Arduino. Получается нужно знать комбинацию из IP +порт и страницы на которую будем отзываться.
        Теоретически комбинацию можно нащупать, и можно придраться и сказать, что это не безопасно, но я для себя решил, что так как доступа к информации нет, то для меня это допустимо. Можно придумать ведь и более сложный механизм, скажем с динамически меняющимся мак-адресом, каждые сутки, отправкой его письмом на почту и проверкой при обращении содержится ли в запросе в заголовках этот мак-адрес и сделать к примеру клиент с отправкой таких заголовков и обращением к данной странице по связке IP+порт… Но стоит ли овчинка выделки?.. )
          0
          Вот тут описан механизм слежения за действиями пользователей у некоторых провайдеров. Вашу секретную ссылку могут просто посещать вслед за вами.
          lleo.me/dnevnik/2015/01/29.html
            0
            Спасибо за ссылку, обязательно ознакомлюсь. Но как описано в статье, тут два варианта. Первый — они включат PC, но не получат к нему доступа, второй — они получат сообщение, что PC уже включен, но не получат к нему доступа. Так что ничего критичного не получаем. Как я говорил, возможность передавать данные специально не реализовывалась с целью безопасности. Стоит отметить, что в 99,9% случаев я посылал сигнал на пробуждение, так как при подключении по RDP на рабочем столе лежит ярлык с командной строкой «C:\Windows\System32\rundll32.exe powrprof.dll,SetSuspendState 0,1,0» которая отправляет PC в «sleep».
            Я ведь не отрицаю, что можно найти эту ссылку, но не вижу в этом ничего критичного. Опять таки, если для кого-то это критично, можно придумать массу вариантов. Вот с ходу могу предложить такой вариант: добавляем в схему DS1307 для работы с реальным временем, делаем автономное резервное питание, делаем хеш функцию с «солью» из набора символов (то есть берем дату или дату плюс текущее значение часа, прогоняем её через хеш функцию, складываем с нашим набором символов, получаем другой хеш, повторяем n раз и на выходе контрольная сумма или дата для хэша, значение часов плюс скажем сто для числа повторений). Таким образом мы получаем клиент с генерацией заголовков и сервер которые будет проверять на совпадение в заголовках контрольного значения с идентичным вычислением на сервере. Ведь для тех кто ищет с чего начать, как раз тут раздолье вариантов. Я не вижу, что использование данного решения было бы опаснее, чем использование «магических пакетов».
              +1
              Вы писали, что у вас есть функция принудительного отключения питания для перезагрузки в случае сбоя компа. Вот она-то уже может попортить крови.

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

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

                В технологии Wake-on-lan изначально функция доступна буквально всему интернету.
                Где гарантии, что провайдеры также не «отдают на сторону» UDP-пакеты?
                По поводу выключения. Никто не мешает перенастроить систему, что при получении сигнала от кнопки питания уходить в сон.
                Но опять таки это не говорит о том, что я с вами не согласен. Теоретически — да, открыт доступ к функции включения всему интернету.
                  0
                  Всё решается гораздо проще. Есть такой алгоритм как KeeLoq который обеспечивает безопасную передачу команды и в настоящее время используется для пультов автосигнализаций. Конкретно с авто происходят фейлы с сильным ослаблением стойкости алгоритма, но сам алгоритм при условии произвольного выбора ключа считается еще не взломаным.
                    0
                    Никогда не думал о применении KeeLoq в такой области? А почему именно этот алгоритм шифрования?
                      0
                      Потому что он простой в реализации. Никаких хеш-функций считать не надо — просто сдвиговый регистр с обратными связями. Нагрузка на микроконтроллер минимальная, лишь бы ключ не светить. Фишка еще в том что пульт передаёт счетчик, и даже если узнаешь ключ приемник может отбросить команду как ложную если переданное значение счетчика будет меньше чем с прошлого сеанса или сильно больше.
                      Алгоритм специально разрабатывался для противодействия воспроизведению перехваченного сигнала, т.е. точно такой же сигнал воспроизведенный приемнику не приведет к повторному действию.
                      Не обязательно воспроизводить весь алгоритм один в один по спецификациям, можно ведь взять только идею.
                        0
                        Кстати, раз уж речь внезапно зашла про KeeLoq, предлагаю небольшой офтоп. Вы понимаете, как они хранят ключи? Я сейчас делаю один девайс, который использует такие брелки, и мне просто стало интересно, как шифрование осуществляется. Про сам алгоритм шифрования, про формат посылки, про счетчик синхронизации — я нашел. Не понял только, как брелок и приемник умудряются зашифровать и расшифровать посылку. Откуда они ключ друг друга знают? Он намертво внутри прошит что ли? У всех одинаковый?
                          0
                          Да, ключи вшиты. Там есть постоянная часть и переменная.
                          Постоянная — одинакова для производителя, а переменная это что-то вроде серийного номера. Ключи соответственно уникальны.
                          Собственно, поэтому и проблемы с брелками наблюдаются — производители используют константы в ключах и эти константы периодически утекают в паблик. Переменной части кода ключа остается не так много как хотелось бы, поэтому они ломаются за приемлемое время на обычном ПК если известна постоянная часть от производителя.
                          Поэтому при утере ключей и необходимости иметь дополнительное количество ключей — меняют весь блок сигнализации т.к. чужие брелки в таком случае не подойдут.
              0
              Можно использовать один из вариантов реализации KeeLoq алгоритма который обеспечит защиту от несанкционированного использования.
              0
              Мне не безынтересны предлагаемые варианты, обязательно почитаю. Просто попытаюсь объяснить свою позицию. Случается так, что забываю у мышки выключить тумблер (on/off), а она с энергосберегающим режимом. При выходе из стендбай она подает какой-то сигнал, который PC воспринимает как сигнал к включению. (И меня это устраивает, так как просто перещелкнув вышеописанный тумблер вывожу PC из сна). Так вот в тех случаях когда тумблер не выключен, жена может просто задеть стол или мышку и запустить PC. И она не будет уверена, она это сделала или я послал сигнал на включение — то есть она не станет его выключать заранее не зная, что именно она его включила. Таким образом вероятность того, что кто-то из интернета включит мне PC ниже чем вероятность, что его физически выведут из сна дома.
                0
                Сталкивался с такой фигней, когда компьютер после выключения был доступен для wake-on-LAN только несколько минут после. Это из-за того, что роутер забывает таблицу сопоставления MAC и IP адресов (ARP таблицу)
                Роутеры не дают часто сделать проброс внешнего порта на порт внутреннего широковещательного .255 адреса…

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

                На D-Linkах выкручивался экзотично — скрипт узнавал адрес роутера по его DYNDNS имени, потом подключался к телнету роутера, вбивал ARP запись, посылал уже WOL пакет…

                Ваше решение решает эти проблемы, я же ленился сделать хардварное решение… корпус там искать…

                Кстати, ждем решения этой проблемы на ESP8266 с nodeMCU, и провод не потребуется, если есть WIFI…
                  +1
                  Это из-за того, что роутер забывает таблицу сопоставления MAC и IP адресов (ARP таблицу)

                  Спасибо за информацию! Нужно будет почитать, может действительно есть решение для моего роутера и arduino освободиться для других проектов )
                    0
                    Любые попытки заставить стабильно работать wake-on-lan
                    Аналогично. Ни один из моих компов за 15 лет стабильно не обрабатывал WOL, Удивительно, технологии два десятка лет а её так и не смогли нормально и удобно реализовать.

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

                    Самое читаемое