[Из песочницы] Обновление сервисов, запущенных на Go
Я люблю программировать на Go, но больше всего сейчас мне нравится программировать в gobot для Raspberry Pi. Каждое изменение в коде требует определенное время на нудные операции, связанные с обновлением кода. Сначала я должен остановить процесс, так как Filezilla отказывается писать в исполняемый файл, когда процесс запущен, загрузить новый исполняемый файл по SFTP и запустить его (это не только нудно, но еще 10–20 секунд простоя, когда процесс остановлен).Аналогичная ситуация меня преследует и при разработке для обычного веба на Go. Именно в gobot я вынужден очень часто обновлять код, что связанно со стилем разработки, который приносит мне удовольствие в свободное время. С разработкой нового пакета обновлять код, написанный на Go стало проще и быстрее.Сейчас расскажу, как пользоваться моим пакетом и как он устроен.
go get github.com/CossackPyra/updater Этой командой вы установили мой updater в ваш Go, также вы можете установить тулзу в командную строку следующей командой: go get github.com/CossackPyra/updater/pyra-poster Вот пример веб-сервиса с возможностью обновления: package main
import ( «fmt» «io» «net/http» «os» «github.com/CossackPyra/updater» )
func main () {
http.HandleFunc (»/», handle_def)
os.Mkdir («tmp», 0700) u1:= updater.UpdaterServer («tmp», []byte (»1234567890123456»), os.Args[0]) http.Handle (»/updater-me», u1) http.ListenAndServe (»:9999», nil) }
func handle_def (w http.ResponseWriter, r *http.Request) { fmt.Println («def », r.Method) io.WriteString (w, «v 24\n») io.WriteString (w, r.URL.Path) println (r.URL.Path) } Именно следующие 3 строчки добавляют возможность обновлять программу: «github.com/CossackPyra/updater» … u1:= updater.UpdaterServer («tmp», []byte (»1234567890123456»), os.Args[0]) http.Handle (»/updater-me», u1) В данном случает все шифруется 16-байтовым ключом []byte (»1234567890123456»), а 31323334353637383930313233343536 это его шестнадцатеричное представление. new-service новый исполняемый файл, и вот команда, чтобы обновить старый процесс. pyra-poster 31323334353637383930313233343536 new-service http://127.0.0.1:9999/updater-me Как это работает? Весь код уместился в 280 строках. У меня больше доверия в коду, в котором можно быстро разобраться. Я не до конца уверен в криптографической стойкости моего алгоритма шифрования и как вообще можно быть уверенным в чем-то подобном, поэтому мне интересно его обсудить с вами.При инициализации хендлера в updater.UpdaterServer, генерится случайная последовательность 16 байт (rand1). Для того, чтобы обновить код, надо выполнить два запроса к хендлеру. Первый GET запрос получает эти случайные 16 байт (rand1). Случайные 16 байт (rand1) и секретный пароль (key1) используются для того, чтобы зашифровать отправляемый исполняемый файл алгоритмом AES и отправить шифрограмму методом POST.
Сначала буфер наполняется данными согласно следующему рецепту: — Случайные 20 байт (это не rand1, а rand0 — в настоящий момент они никак не используются); — 20 байт — хеш исполняемого файла sha1; — «pyra-poster» — последовательность байт, название протокола; — 6 байт (1 — int16 Little Endian, 0 — int32 Little Endian) — версия протокола; — сам исполняемый файл.
На этот буфер налагается гамма-функция методом xor, полученная блочным шифром AES (key1, rand1). В результате получается, шифротекст, который отправляется в хендлер методом POST.
На сервере для дешифрования на последовательность накладывается гамма AES (key1, rand1), проверяется заголовок «pyra-poster»(1,0), исполняемый файл сохраняется во временную папку и вычисляется хеш по алгоритму sha1 и сравнивается со sha1 из заголовка. Если хеши равны, то можно полагать с большой вероятностью, что это аутентичный файл созданный хозяином сервиса.
После обновления сервиса rand1 меняется и поэтому, перехватив шифротекст, повторно загрузить его нельзя. Рассчитать key1, имея rand1, и зная особенность заголовка «pyra-poster»(1,0) или, даже имея исполняемый файл, также достаточно сложно.
16-байтовый (128 бит) ключ key1 можно заменить на 32-байтовый (256 бит) без каких-либо дополнительных изменений в коде. Большинство веб броузеров как раз используют шифрование AES 256 бит.
Пользуйтесь на здоровье.