Golang中的持久隐藏服务

p8h8hvxi  于 5个月前  发布在  Go
关注(0)|答案(2)|浏览(46)

我试图使用github.com/cretz/bine/tor在golang中托管一个隐藏服务,但每次我启动程序时,都会启动一个新的隐藏服务(带有新的.onion地址),而不是以前的隐藏服务。
这是我使用的代码

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

字符串
我尝试这样做是为了迫使程序使用相同的DataDir
第一个月
但这行不通。

hiz5n14c

hiz5n14c1#

您需要创建并存储一个密钥,然后将其传递给ListenConf:
参见:https://github.com/cretz/bine/blob/master/tor/listen.go#L56
注意事项:
// Key是要使用的私钥。如果不存在,则生成密钥。
您正在使用的库提供了一个函数来完成此操作。
参见:https://github.com/cretz/bine/blob/b9d31d9c786616742e39a121b60522e803e96731/torutil/ed25519/ed25519.go#L132
执行此操作一次并保存privateKeyString

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

字符串
然后在服务器代码中:

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

ct3nt3jp

ct3nt3jp2#

创建密钥、保存密钥并将其传递给ListenConf的过程非常完美。
下面是我修改后的代码:

package main

import (
    "context"
    "encoding/hex"
    "encoding/json"
    "fmt"
    "github.com/cretz/bine/torutil/ed25519"
    "log"
    "net/http"
    "os"
    "sync"
    "time"

    "github.com/cretz/bine/tor"
)

func saveServiceInfo(key string) error {
    file, err := os.Create("serviceinfo.json")
    if err != nil {
        return err
    }
    defer file.Close()

    encoder := json.NewEncoder(file)
    return encoder.Encode(key)
}

func loadServiceInfo() (string, error) {
    file, err := os.Open("serviceinfo.json")
    if err != nil {
        return "", err
    }
    defer file.Close()
    decoder := json.NewDecoder(file)
    var key string
    if err := decoder.Decode(&key); err != nil {
        return "", err
    }
    return key, nil
}

func startHiddenService(privateKey ed25519.PrivateKey, wg *sync.WaitGroup) {
    defer wg.Done() // Decrement the WaitGroup counter when the goroutine completes
    fmt.Println("Starting the onion service, please wait a couple of minutes...")
    t, err := tor.Start(nil, &tor.StartConf{DataDir: "tor-data"})
    if err != nil {
        log.Panicf("Unable to start Tor: %v", err)
    }
    defer t.Close()

    listenCtx, listenCancel := context.WithTimeout(context.Background(), 3*time.Minute)
    defer listenCancel()

    onion, err := t.Listen(listenCtx, &tor.ListenConf{Version3: true, Key: privateKey, 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
    }()

    // Wait for either an error or user input
    err = <-errCh
    if err != nil {
        log.Printf("Failed serving: %v", err)
    }
}

func main() {
    var privateKey string

    if _, err := os.Stat("serviceinfo.json"); err == nil {
        fmt.Println("Loading saved onion service...")

        // Load the service private key if the file exists
        privateKey, err = loadServiceInfo()
        if err != nil {
            log.Panicf("Failed to load service info: %v", err)
        }

        privateKeyBytes, _ := hex.DecodeString(privateKey)
        privateKey := ed25519.PrivateKey(privateKeyBytes)

        // Start hidden service with the stored private key
        var wg sync.WaitGroup
        wg.Add(1)
        go startHiddenService(privateKey, &wg)
        wg.Wait()

    } else {
        // Create a new onion service
        fmt.Println("Creating new onion service...")

        // Generate a new Ed25519 private key
        keyPair, _ := ed25519.GenerateKey(nil)
        privateKey = hex.EncodeToString(keyPair.PrivateKey())

        // Save the private key
        err = saveServiceInfo(privateKey)
        if err != nil {
            log.Panicf("Failed to save service info: %v", err)
        }

        // Start hidden service with the stored private key
        var wg sync.WaitGroup
        wg.Add(1)
        go startHiddenService(keyPair.PrivateKey(), &wg)
        wg.Wait()
    }
}

字符串

相关问题