81 lines
1.7 KiB
Go
81 lines
1.7 KiB
Go
package server
|
|
|
|
import (
|
|
"crypto/rsa"
|
|
"log"
|
|
"math/rand"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/Yawning/bulb"
|
|
"github.com/sycamoreone/orc/tor"
|
|
)
|
|
|
|
// TorConfig is a wrapper struct for tor configuration.
|
|
type TorConfig struct {
|
|
DataDir string
|
|
HashedControlPassword string
|
|
ClearPassword string
|
|
Timeout time.Duration
|
|
}
|
|
|
|
// StartTor starts a new instance of tor or doesn't with the reason why.
|
|
func StartTor(cfg TorConfig) (*Tor, error) {
|
|
tc := tor.NewConfig()
|
|
tc.Set("DataDirectory", cfg.DataDir)
|
|
tc.Set("HashedControlPassword", cfg.HashedControlPassword)
|
|
tc.Set("SocksPort", "0")
|
|
cp := rand.Intn(64512)
|
|
tc.Set("ControlPort", cp)
|
|
tc.Timeout = cfg.Timeout
|
|
|
|
tcmd, err := tor.NewCmd(tc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = tcmd.Start()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
log.Println("tor started, sleeping for a few seconds for it to settle...")
|
|
time.Sleep(5 * time.Second)
|
|
|
|
bc, err := bulb.Dial("tcp", "127.0.0.1:"+strconv.Itoa(cp))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
err = bc.Authenticate(cfg.ClearPassword)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
t := &Tor{
|
|
tc: tc,
|
|
tcmd: tcmd,
|
|
bc: bc,
|
|
}
|
|
|
|
return t, nil
|
|
}
|
|
|
|
// Tor is a higher level wrapper to a child tor process
|
|
type Tor struct {
|
|
tc *tor.Config
|
|
tcmd *tor.Cmd
|
|
bc *bulb.Conn
|
|
}
|
|
|
|
// AddOnion adds an onion service to this machine with the given private key
|
|
// (can be nil for an auto-generated key), virtual onion port and TCP destunation.
|
|
func (t *Tor) AddOnion(pKey *rsa.PrivateKey, virtPort uint16, destination string) (*bulb.OnionInfo, error) {
|
|
return t.bc.AddOnion([]bulb.OnionPortSpec{
|
|
{
|
|
VirtPort: virtPort,
|
|
Target: destination,
|
|
},
|
|
}, pKey, true)
|
|
}
|