Подобная задача удаленной установки софта, проверки состояния, дистанционного выключения/перезагрузки большой группы 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 и рестартить сервис.
[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)
mvs
04.06.2015 00:08Зачем telnet в конфиге?
Под каким пользователем windows работает ssh-сервис и от чьёго имени будут выполняться команды?
Зачем везде вызовы cmd, если 1) она и так указана в SSHCMD и 2) большинство команд не нуждаются в консоли?
Поясните, пожалуйста, ключи при подключении по ssh, особенно обнуление knownHosts.
> Демо-програмка на Python, которая опрашивает компы в диапазоне
Поздравляю, вы изобрели Ansible.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 лишних вопросов не будет.
Понимаю, что где-то нарушил секюрность, но несильно.mvs
05.06.2015 16:55Наверное, стоит тогда убрать из конфига всё остальное про telnet, чтобы не вводить в заблужедение.
> Понимаю, что где-то нарушил секюрность, но несильно.
Как-то вообще не секурно. SSH предупреждает и не даёт подключаться к хосту, если внезапно изменился его ключ. И это правильно, т.к. позволяет заметить mitm (подмену ключа).rrrav Автор
06.06.2015 11:34Конфиг стандартный, его генерит сама программа в момент установки. Поэтому придется оставить все пункты, а ненужное отключить явно.
Защита SSH немного нарушена, но атака подменой ключа в данном случае бессмысленна — атакующий не подключается к серверу, это сервер подключается к нему и выполняет на нем команду (может быть даже команду заливки другого образа).
Ну и почему так было сделано — на компах установлено несколько ОС, а загрузка выбирается по сети (PXE). Поэтому на одном IP может оказаться другой хост и в стандартном варианте SSH отвергнет соединение.
rrrav Автор
04.06.2015 00:28>Поздравляю, вы изобрели Ansible.
Нас уже 6 миллиардов (даже больше) — велосипедов, в пределе, можем изобрести где-то столько.
rrrav Автор
04.06.2015 00:32> Зачем везде вызовы cmd
так оказалось универсальнее. Практически всегда работает. Без этого — только отдельные команды. Умом винду не понять, аршином общим не измерить…pvasili
05.06.2015 19:59Нужно не мерить своим аршином и своим умом (изобретателя своего велосипеда), а использовать стандартные для данной OS методы :)
rrrav Автор
04.06.2015 00:36> большинство команд не нуждаются в консоли
немного не понял, но есть программы, который выводят в форточки, а есть — в консоль. В Винде первых больше. Ну и не нашел я этой фразы в тексте??mvs
05.06.2015 17:00Из ваших примеров: зачем консоль (cmd /c) для shutdown, для установки 1С, тем более, когда в конфиге уже есть SSHCMD=C:\Windows\system32\cmd.exe?
Это фича сугубо FreeSSHD, которому нужна консоль и для авторизации пользователей и для запуска любой команды, или просто для пущей уверенности?rrrav Автор
07.06.2015 11:23Да, shutdown работает и без cmd /c. Но многие команды без этого не работают. Нужно универсальное решение. Например, запустить командный файл, расположенный на сетевом ресурсе.
rrrav Автор
04.06.2015 11:24Кстати в тему совпадение — habrahabr.ru/post/259449 — MS собирается внедрить поддержку SSH в Windows.
Надо было, конечно, лет 20 назад это сделать.
bormotov
05.06.2015 15:50Если компьютеров много, нужно сразу взять Ansible (раз уж вы начали про sshd).
Мы для себя выбрали SaltStack, у него родной клиент для windows, умеет в том числе и запускать что-то. Прелесть варианта «с клиентом», что компьютеру, которым нужно управлять из центра, достаточно иметь выход наружу, то есть он легко может находиться за кучей NAT.
rrrav Автор
05.06.2015 16:41Ansible не дружит с Windows.
SaltStack, судя по отзывам, еще недостаточно стабилен.
У меня задача собственно была простая — все компьютеры в локалке (учебные классы), нужно иметь возможность их удаленно перезагрузить/выключить, запустить копирование данных с сервера, запустить установку обновлений.
Все это через freeSSHd получилось просто и стабильно.
Ну и кстати, управление успешно работает не только из Linux, но и из Windows (используя пакет Putty)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.
и списку модулей на docs.ansible.com/list_of_windows_modules.html должен уметь. Но утверждать не буду, т.к. сам работаю с ним только для Linux.
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.
Если руки дойдут — могу проверить базовую поддержку для Windows.rrrav Автор
05.06.2015 17:34Это уже интересно.
Жалко, правда, что не удастся авторизоваться через ssh public key — просто и надежно, а здесь — uses native PowerShell. Если все в одном домене/лесе, то нормально, а если есть Home Edition, то сложнее.
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 из списков живущих.
Jirvil
Было бы неплохо рассказать про плюсы и минусы относительно winexec.
rrrav Автор
Я не пробовал winexec, поэтому сравнить не смогу. К тому времени, когда вышла статья на хабре про winexec, у меня уже давно работала система на freeSSHd. Работала (и работает) почти без проблем, а написать собрался только 5 лет спустя, может кому-нибудь пригодится.
Некоторые проблемы появились только на последних версиях Windows — потребовалась настройка Брандмауэра.
rrrav Автор
Один момент, который в некоторых случаях имеет значение — winexec, как я понял использует RPC. Это либо авторизация в домене, либо локальные пользователи (с админ правами). В принципе все правильно, если все в одном домене.
Но иной раз появляются в сети ноутбуки с Home версией Windows — в домен его уже не введешь. В случае с freeSSHd все инвариантно к домену, системе и т.д. — решается на уровне ssh протокола, который вполне надежный, защищенный, нужен только публичный ключ, который и защищать не нужно.