gopersistencetor

Persistent hidden service in golang


Im trying to host a hidden service in golang using github.com/cretz/bine/tor. But every time I start my program a new hidden service (with new .onion adress) is started instead of the previous hidden service.

This is the code Im using

package main

import (
    "context"
    "fmt"
    "github.com/cretz/bine/tor"
    "log"
    "net/http"
    "time"
)

func main() {
    // Start tor with default config
    fmt.Println("Starting and registering onion service, please wait a couple of minutes...")
    t, err := tor.Start(nil, nil)
    if err != nil {
        log.Panicf("Unable to start Tor: %v", err)
    }
    defer t.Close()
    // Wait at most a few minutes to publish the service
    listenCtx, listenCancel := context.WithTimeout(context.Background(), 3*time.Minute)
    defer listenCancel()
    // Create a v3 onion service
    onion, err := t.Listen(listenCtx, &tor.ListenConf{Version3: true, RemotePorts: []int{80}})
    if err != nil {
        log.Panicf("Unable to create onion service: %v", err)
    }
    defer onion.Close()
    fmt.Printf("Open Tor browser and navigate to http://%v.onion\n", onion.ID)
    fmt.Println("Press enter to exit")
    // Serve the current folder from HTTP
    errCh := make(chan error, 1)
    go func() { errCh <- http.Serve(onion, http.FileServer(http.Dir("."))) }()
    // End when enter is pressed
    go func() {
        fmt.Scanln()
        errCh <- nil
    }()
    if err = <-errCh; err != nil {
        log.Panicf("Failed serving: %v", err)
    }
}


I tryed this to force the program using the same DataDir

t, err := tor.Start(nil, &tor.StartConf{DataDir: "data-dir"})

but this wont work.


Solution

  • You need to create and store a key, which you then pass to ListenConf:

    See: https://github.com/cretz/bine/blob/master/tor/listen.go#L56

    Note:

    // Key is the private key to use. If not present, a key is generated.

    The lib you're using offers a function to do this.

    See: https://github.com/cretz/bine/blob/b9d31d9c786616742e39a121b60522e803e96731/torutil/ed25519/ed25519.go#L132

    Do this once and save privateKeyString:

    keyPair, _ := ed25519.GenerateKey()
    privateKeyString := hex.EncodeToString(keyPair.PrivateKey())
    

    And then in your server code:

    privateKeyBytes, _ := hex.DecodeString(privateKeyString)
    privateKey := ed25519.PrivateKey(privateKeyBytes)
    lc := &tor.ListenConf{
        Key: privateKey,
        Version3: true,
        RemotePorts: []int{80}
    }