Skip to content

Instantly share code, notes, and snippets.

@Danukeru
Last active November 8, 2023 17:58
Show Gist options
  • Save Danukeru/8edb2ea5ece6f59f2bf5904ca8865feb to your computer and use it in GitHub Desktop.
Save Danukeru/8edb2ea5ece6f59f2bf5904ca8865feb to your computer and use it in GitHub Desktop.
package main
import (
"context"
"fmt"
"log"
"net/url"
"net/http"
"net/http/httputil"
"os"
"time"
b64 "encoding/base64"
"github.com/cretz/bine/tor"
"github.com/cretz/bine/torutil/ed25519"
"github.com/ipsn/go-libtor"
)
// NewProxy takes target host and creates a reverse proxy
func NewProxy(targetHost string) (*httputil.ReverseProxy, error) {
url, err := url.Parse(targetHost)
if err != nil {
return nil, err
}
return httputil.NewSingleHostReverseProxy(url), nil
}
// ProxyRequestHandler handles the http request using proxy
func ProxyRequestHandler(proxy *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
proxy.ServeHTTP(w, r)
}
}
func main() {
// Start tor with some defaults + elevated verbosity
fmt.Println("Starting and registering onion service, please wait a bit...")
t, err := tor.Start(nil, &tor.StartConf{ProcessCreator: libtor.Creator, DebugWriter: os.Stderr})
if err != nil {
log.Panicf("Failed to start tor: %v", err)
}
defer t.Close()
// Wait at most a few minutes to publish the service
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
defer cancel()
// $ dd if=/dev/urandom bs=64 count=1 status=none| base64 -w100
// OR if you generated a vanity address, use this to dump the last 64 bytes from a stored onion-V3 :
// $ dd if=hs_ed25519_secret_key skip=32 bs=1 status=none | base64 -w 100
_b64Ed25519 := "vnHA4KseeuhvqUKp3hoMqNiy0XA+cEPXWeD0B6fsXwIS3ZufjmB9GpnI+oLs1SdrmFqtlyFSaQNDLm38UNIRTg=="
// default goes to -> testkeyskerhr4w3njfge5fyumi6nmhom73icpwbpiw35ctfwdexjyid.onion
// $ export B64TOR="base64stringfor64bytesofkeymaterial=="
if( len(os.Getenv("B64TOR")) == 88 ) {
_b64Ed25519 = os.Getenv("B64TOR")
}
_key, _ := b64.StdEncoding.DecodeString(_b64Ed25519)
// Create an onion service to listen on any port but show as 80
onion, err := t.Listen(ctx, &tor.ListenConf{RemotePorts: []int{80}, Version3: true, Key: ed25519.PrivateKey(_key)})
if err != nil {
log.Panicf("Failed to create onion service: %v", err)
}
defer onion.Close()
fmt.Printf("Please open a Tor capable browser and navigate to http://%v.onion\n", onion.ID)
// initialize a reverse proxy and pass the actual backend server url here
proxy, err := NewProxy("http://127.0.0.1:9000")
if err != nil {
panic(err)
}
// handle all requests to your server using the proxy
http.HandleFunc("/", ProxyRequestHandler(proxy))
log.Fatal(http.Serve(onion, nil))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment