Здесь рассматривалась задача управления компьютером на Windows из Linux. Решалась с помощью winexe.

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

На сайте лежит только последняя версия freeSSHd — 1.3.1. У меня она работает неустойчиво (иногда падает сервис). Предыдущая версия — 1.2.4 — работает прекрасно от XP до Win8.1, хотя и есть небольшой эксплоит — но вроде ничего кроме, как завалить сервис FreeSSHDService не получается, поэтому можно закрыть на это глаза. На всякий случай положил эту версию здесь (размер — 782456)

Запускаем установщик, в процессе меняем путь установки («C:\Program Files (x86)\FreeSSHD») на C:\bin\FreeSSHD — так проще его найти на системах с разной архитектурой и конфиг будет везде одинаковый. (C:\bin надо предварительно создать.)

Дальше все по умолчанию — в конце запускается сервис FreeSSHDService. Его можно настроить, щелкнув значок в трее, но проще скопировать готовые настройки в файл настроек C:\bin\FreeSSHD\FreeSSHDService.ini и рестартить сервис.
Пример FreeSSHDService.ini:
[Telnet server]
TelnetListenAddress=0.0.0.0
TelnetListenPort=23
TelnetMaxConnections=0
TelnetTimeout=0
TelnetBanner=
TelnetCMD=C:\Windows\system32\cmd.exe
TelnetRun=0
TelnetNewConsole=1
[SSH server]
SSHListenAddress=0.0.0.0
SSHListenPort=22
SSHMaxConnections=0
SSHTimeout=0
SSHBanner=
SSHCMD=C:\Windows\system32\cmd.exe
SSHRun=1
SSHNewConsole=1
SSHCiphers=0
SSHMACs=65535
SSHPasswordAuth=0
SSHPublickeyAuth=0
SSHPublickeyPath=C:\bin\freeSSHdRSAKeyPath=C:\bin\freeSSHd\RSAKey.cfg
DSAKeyPath=C:\bin\freeSSHd\DSAKey.cfg
[SSH tunneling]
SSHLocalTunnel=0
SSHLocalTunnelOnly=0
SSHRemoteTunnel=0
SSHRemoteTunnelOnly=0
[SFTP]
SFTPHomePath=$HOME[Access filtering]
HostRestrictions=
HostRestrictionsAllow=0
[Logging]
LogEvents=0
LogFilePath=C:\bin\freeSSHd\freesshd.log
LogResolveIP=0
[Automatic updates]
UpdateCheckOnStartup=0
UpdateDontPrompt=0
UpdateShowMessages=1
UpdateLastMessageID=0
[Users]
UserCount=1
[User0]
Name=admin
Auth=2
Password=000000000000000000000000000000000000000000
Domain=
Shell=1
SFTP=1
Tunnel=1

Теперь надо дооформить объявленного юзера admin — создать файл C:\bin\FreeSSHD\admin и записать туда публичный ключ.

Либо используем уже имеющийся id_dsa.pub, либо в консоли Linux набираем
/# ssh-keygen -t dsa

и получаем пару ключей — id_dsa и id_dsa.pub
На Windows копируем id_dsa.pub в каталог C:\bin\FreeSSHD и переименовываем в C:\bin\FreeSSHD\admin

Рестартим сервис FreeSSHDService:
net stop FreeSSHDService & net start FreeSSHDService


На Linux проверяем подключение (листинг корня C:\):
/# ssh -2q -i <my_key_files_path>/id_dsa -ladmin -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null <Win_Host_IP> "cmd /c dir c:\\"

Если хост отверг подключение (на win7-win8 вероятно), настраиваем Брандмауэр в «Центре управления сетями ...»:
Брандмауэр Windows -> устранение неполадок в сети -> входящие подключения -> что-то другое -> обзор -> C:\bin\FreeSSHD\FreeSSHDService.exe

Если все получилось, копируем каталог C:\bin\FreeSSHD\ на все прочие компы — тогда во время установки FreeSSHD задаст гораздо меньше вопросов и запустится уже настроенный. Можно, конечно, это все и настройку Брандмауэра реализовать через Group Policy, но я этим не заморачивался — все компы клонировались из одного удачного образа.

Теперь на любом компе можно выполнить любую (почти) команду.
Например, перезагрузка:
/# ssh -2q -i <my_key_files_path>/id_dsa -ladmin -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null <Win_Host_IP> "cmd /c shutdown /r /t 1"


Установка 1с (тихая):
/# ssh -2q -i <my_key_files_path>/id_dsa -ladmin -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null  <Win_Host_IP> "cmd /c  start \\\\<Server_IP>\\buh\\1Ccurrent\\setup /s"

Поскольку доступ консольный, то при попытке запуска программы с GUI надо использовать запуск из нового окна — «start ». Хотя тихая установка 1C и не требует GUI.

Когда компьютеров много, запуск команд по очереди неэффективен, надо форкать сессии.
Демо-програмка на Python, которая опрашивает компы в диапазоне 192.168.0.210-192.168.0.220 и записывает их имена в лог /tmp/rexec.log. Не ответившие помечаются как NA, а зависшие сессии — ?T:
#!/usr/bin/python
# -*- coding: utf-8 -*-

log = '/tmp/rexec.log'
host_range = range(210,220)
ip_first_3 = '192.168.0'
my_key = '/root/.ssh/id_dsa'

my_cmd = 'hostname' #имена компов
#my_cmd = 'shutdown /s /t 10' #выключить 
#my_cmd = r'\\\\srv1\\shar1\\mycmd.bat' # выполнить командный файл с сетевого ресурса

import os,sys,time,subprocess
from datetime import datetime

try:
    cmd = '/usr/bin/ssh -2q -oBatchMode=yes -oStrictHostKeyChecking=no -oUserKnownHostsFile=/dev/null -i%s -ladmin %s.%%d "cmd /c %s " ' % (my_key,ip_first_3,my_cmd)
    procs,out,err = [],[],[]
    for x in host_range:
        xcmd = cmd % x
        procs.append([x,subprocess.Popen(xcmd,stdout=subprocess.PIPE,stderr=subprocess.STDOUT,shell=True,bufsize=4096,executable='/bin/bash')])
    for i in range(0,20): #20 циклов по 1 сек
        stop = True
        for proc in procs:
#            print i, proc[0]
            if proc[0] == 0: continue
            try: 
                res = proc[1].poll()
                if res == None: 
                    stop = False
                    continue
                if res == 0: out.append("%d:%s" % (proc[0],proc[1].stdout.read().splitlines()[0])) #берем только 1 строку вывода !
                else: err.append("%d:NA" % proc[0])
            except: err.append("%d:EX" % proc[0])
            proc[0]=0
        if stop: break
        time.sleep(1)
    if not stop: #убиваем оставшиеся сессии    
        for proc in procs:
            if proc[0] != 0:
                proc[1].terminate()
                err.append("%d:?T" % proc[0])
    s = "%s|%s" % ('; '.join(out),'; '.join(err))
except:
    s = "!!! Error"
print s
with open(log, "ab") as fp:
    fp.write("--- %s cmd=%s\n" % (datetime.strftime(datetime.now(), "%Y.%m.%d %H:%M:%S"),my_cmd))
    fp.write(" Result: %s\n" % s)

(Исходная программа была CGI-скриптом, отсюда такой минимализм вывода)

Сложные и длинные команды лучше оформлять в виде пакетного файла и размещать в доступном сетевом пути. На Samba ресурсе надо дать файлу права на выполнение и оформить концы строк в стиле Windows.

Комментарии (26)


  1. Jirvil
    03.06.2015 22:00

    Было бы неплохо рассказать про плюсы и минусы относительно winexec.


    1. rrrav Автор
      03.06.2015 23:12
      +1

      Я не пробовал winexec, поэтому сравнить не смогу. К тому времени, когда вышла статья на хабре про winexec, у меня уже давно работала система на freeSSHd. Работала (и работает) почти без проблем, а написать собрался только 5 лет спустя, может кому-нибудь пригодится.
      Некоторые проблемы появились только на последних версиях Windows — потребовалась настройка Брандмауэра.


    1. rrrav Автор
      03.06.2015 23:47

      Один момент, который в некоторых случаях имеет значение — winexec, как я понял использует RPC. Это либо авторизация в домене, либо локальные пользователи (с админ правами). В принципе все правильно, если все в одном домене.
      Но иной раз появляются в сети ноутбуки с Home версией Windows — в домен его уже не введешь. В случае с freeSSHd все инвариантно к домену, системе и т.д. — решается на уровне ssh протокола, который вполне надежный, защищенный, нужен только публичный ключ, который и защищать не нужно.


  1. FanAs
    03.06.2015 22:38

    А нет ли чего-то подобного для PowerShell разве?


    1. rrrav Автор
      03.06.2015 23:17

      В смысле скрипт на PowerShell слушает на сокете команды, которые ему посылает клиент (в данном случае из Линукса)? Мне пока такие решения не попадались.


      1. symbix
        04.06.2015 01:46

        sharpcodenotes.blogspot.ru/2014/01/running-powershell-commands-from-linux.html


        1. rrrav Автор
          04.06.2015 10:26

          Да, интересная вещь, этот WSMAN, спасибо за подсказку. Только когда я делал свою систему, он еще не был на слуху. Да и сам PowerShell тогда только появился


  1. mvs
    04.06.2015 00:08

    Зачем telnet в конфиге?
    Под каким пользователем windows работает ssh-сервис и от чьёго имени будут выполняться команды?
    Зачем везде вызовы cmd, если 1) она и так указана в SSHCMD и 2) большинство команд не нуждаются в консоли?
    Поясните, пожалуйста, ключи при подключении по ssh, особенно обнуление knownHosts.

    > Демо-програмка на Python, которая опрашивает компы в диапазоне
    Поздравляю, вы изобрели Ansible.


    1. rrrav Автор
      04.06.2015 00:23

      В конфиге описывается даже то, что не живет:
      TelnetRun=0
      — он не стартует (поскольку дыра)

      -2 — версия протокола (оказалось существенно)
      -q — без лишних предупреждений
      -i <my_key_files_path>/id_dsa -ladmin — тут все понятно
      -oStrictHostKeyChecking=no — иначе будет ждать подтверждения о принятии нового хоста
      -oUserKnownHostsFile=/dev/null — если на том же IP адресе/имени оказался другой хост (редко, но случается), защита ssh отвергнет коннект. Здесь у нас всегда все хосты новые (каждый новый — плевок в пустоту). В купе с опцией -q лишних вопросов не будет.
      Понимаю, что где-то нарушил секюрность, но несильно.


      1. mvs
        05.06.2015 16:55

        Наверное, стоит тогда убрать из конфига всё остальное про telnet, чтобы не вводить в заблужедение.

        > Понимаю, что где-то нарушил секюрность, но несильно.
        Как-то вообще не секурно. SSH предупреждает и не даёт подключаться к хосту, если внезапно изменился его ключ. И это правильно, т.к. позволяет заметить mitm (подмену ключа).


        1. rrrav Автор
          06.06.2015 11:34

          Конфиг стандартный, его генерит сама программа в момент установки. Поэтому придется оставить все пункты, а ненужное отключить явно.
          Защита SSH немного нарушена, но атака подменой ключа в данном случае бессмысленна — атакующий не подключается к серверу, это сервер подключается к нему и выполняет на нем команду (может быть даже команду заливки другого образа).
          Ну и почему так было сделано — на компах установлено несколько ОС, а загрузка выбирается по сети (PXE). Поэтому на одном IP может оказаться другой хост и в стандартном варианте SSH отвергнет соединение.


    1. rrrav Автор
      04.06.2015 00:28

      >Поздравляю, вы изобрели Ansible.
      Нас уже 6 миллиардов (даже больше) — велосипедов, в пределе, можем изобрести где-то столько.


    1. rrrav Автор
      04.06.2015 00:29

      > Под каким пользователем windows работает ssh-сервис
      SYSTEM


      1. mvs
        05.06.2015 16:56

        Т.е. как-то образом авторизовавшись в ssh, не важно, под каким именно пользователем, я получу неограниченные привилегии в Windows?


        1. rrrav Автор
          07.06.2015 11:18

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


    1. rrrav Автор
      04.06.2015 00:32

      > Зачем везде вызовы cmd
      так оказалось универсальнее. Практически всегда работает. Без этого — только отдельные команды. Умом винду не понять, аршином общим не измерить…


      1. pvasili
        05.06.2015 19:59

        Нужно не мерить своим аршином и своим умом (изобретателя своего велосипеда), а использовать стандартные для данной OS методы :)


    1. rrrav Автор
      04.06.2015 00:36

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


      1. mvs
        05.06.2015 17:00

        Из ваших примеров: зачем консоль (cmd /c) для shutdown, для установки 1С, тем более, когда в конфиге уже есть SSHCMD=C:\Windows\system32\cmd.exe?
        Это фича сугубо FreeSSHD, которому нужна консоль и для авторизации пользователей и для запуска любой команды, или просто для пущей уверенности?


        1. rrrav Автор
          07.06.2015 11:23

          Да, shutdown работает и без cmd /c. Но многие команды без этого не работают. Нужно универсальное решение. Например, запустить командный файл, расположенный на сетевом ресурсе.


  1. rrrav Автор
    04.06.2015 11:24

    Кстати в тему совпадение — habrahabr.ru/post/259449 — MS собирается внедрить поддержку SSH в Windows.
    Надо было, конечно, лет 20 назад это сделать.


  1. bormotov
    05.06.2015 15:50

    Если компьютеров много, нужно сразу взять Ansible (раз уж вы начали про sshd).

    Мы для себя выбрали SaltStack, у него родной клиент для windows, умеет в том числе и запускать что-то. Прелесть варианта «с клиентом», что компьютеру, которым нужно управлять из центра, достаточно иметь выход наружу, то есть он легко может находиться за кучей NAT.


  1. rrrav Автор
    05.06.2015 16:41

    Ansible не дружит с Windows.
    SaltStack, судя по отзывам, еще недостаточно стабилен.
    У меня задача собственно была простая — все компьютеры в локалке (учебные классы), нужно иметь возможность их удаленно перезагрузить/выключить, запустить копирование данных с сервера, запустить установку обновлений.
    Все это через freeSSHd получилось просто и стабильно.
    Ну и кстати, управление успешно работает не только из Linux, но и из Windows (используя пакет Putty)


    1. mvs
      05.06.2015 17:02

      Судя по docs.ansible.com/intro_windows.html

      Starting in version 1.7, Ansible also contains support for managing Windows machines. This uses native PowerShell remoting, rather than SSH.

      Ansible will still be run from a Linux control machine, and uses the “winrm” Python module to talk to remote hosts.

      No additional software needs to be installed on the remote machines for Ansible to manage them, it still maintains the agentless properties that make it popular on Linux/Unix.
      и списку модулей на docs.ansible.com/list_of_windows_modules.html должен уметь. Но утверждать не буду, т.к. сам работаю с ним только для Linux.
      Если руки дойдут — могу проверить базовую поддержку для Windows.


      1. rrrav Автор
        05.06.2015 17:34

        Это уже интересно.
        Жалко, правда, что не удастся авторизоваться через ssh public key — просто и надежно, а здесь — uses native PowerShell. Если все в одном домене/лесе, то нормально, а если есть Home Edition, то сложнее.


      1. rrrav Автор
        05.06.2015 17:40

        И вот еще один момент —

        PowerShell 3.0 or higher is needed for most provided Ansible modules for Windows, and is also required to run the above setup script. Note that PowerShell 3.0 is only supported on Windows 7 SP1, Windows Server 2008 SP1, and later releases of Windows.

        У нас еще есть часть компов на XP (как вариант сетевой загрузки). Пожалуй, в нашей реальности еще рано исключать XP из списков живущих.