Updating services running on Go

I love programming on Go, but most of all now I like to program on gobot for the Raspberry Pi. Each change in the code requires a certain time for tedious operations associated with updating the code. First I have to stop the process, because Filezilla refuses to write to the executable when the process is running, download the new executable via SFTP and start it (this is not only tedious, but another 10-20 seconds of downtime when the process is stopped).

A similar situation haunts me when developing for a regular web on Go. It is in gobot that I have to update the code very often, which is connected with the development style, which brings me pleasure in my free time. With the development of the new package, updating code written in Go has become easier and faster.

Now I’ll tell you how to use my package and how it works.

go get github.com/CossackPyra/updater  

With this command you installed my updater in your Go, you can also install tools in the command line with the following command:

go get github.com/CossackPyra/updater/pyra-poster

Here is an example of a web service with the ability to update:

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)
}

It is the following 3 lines that add the ability to update the program:

    "github.com/CossackPyra/updater"
...
    u1 := updater.UpdaterServer("tmp", []byte("1234567890123456"), os.Args[0])
    http.Handle("/updater-me", u1)

In this case, everything is encrypted with the 16-byte key [] byte ("1234567890123456") , and 31323334353637383930313233343536 is its hexadecimal representation. new-service is the new executable, and here is the command to update the old process.

pyra-poster 31323334353637383930313233343536 new-service http://127.0.0.1:9999/updater-me

How it works?


All code fits in 280 lines. I have more confidence in the code, which you can quickly figure out. I’m not completely sure of the cryptographic strength of my encryption algorithm and how you can be sure of something like that, so I’m interested in discussing it with you.

At initialization handler in updater.UpdaterServer, it generates a random sequence of 16 bytes (rand1). In order to update the code, you need to make two requests to the handler. The first GET request receives these random 16 bytes (rand1). Random 16 bytes (rand1) and a secret password (key1) are used to encrypt the sent executable file with the AES algorithm and send the cipher program using the POST method.

First, the buffer is filled with data according to the following recipe:
- Random 20 bytes (this is not rand1, but rand0 - at the moment they are not used at all);
- 20 bytes - hash of sha1 executable file;
- "pyra-poster" - a sequence of bytes, the name of the protocol;
- 6 bytes (1 - int16 Little Endian, 0 - int32 Little Endian) - protocol version;
- the executable file itself.

This gamma function is superimposed on this buffer using the xor method obtained by the AES block cipher (key1, rand1). The result is a ciphertext that is sent to the handler using the POST method.

On the server for decryption, the AES gamut (key1, rand1) is superimposed on the sequence, the “pyra-poster” (1,0) header is checked, the executable file is saved in a temporary folder and the hash is calculated using the sha1 algorithm and compared with sha1 from the header. If the hashes are equal , then we can assume with high probability that this is an authentic file created by the owner of the service.

After updating the rand1 service, it changes and therefore, having intercepted the ciphertext, it cannot be reloaded. Calculating key1, having rand1, and knowing the peculiarity of the header “pyra-poster” (1,0) or even having an executable, is also quite difficult.

The 16-byte (128 bit) key1 can be replaced with 32-byte (256 bit) without any additional changes to the code. Most web browsers just use AES 256 bit encryption.

Use on health.

Also popular now: