Initial commit
This commit is contained in:
commit
fc0962b16c
|
@ -0,0 +1,29 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/rpc"
|
||||
|
||||
"git.xeserv.us/xena/route/routerpc"
|
||||
)
|
||||
|
||||
func main() {
|
||||
client, err := rpc.DialHTTP("tcp", "127.0.0.1:9234")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
req := routerpc.AddHostRequest{
|
||||
APIKey: "hunter2",
|
||||
Hostname: "",
|
||||
PrivKey: nil,
|
||||
}
|
||||
resp := &routerpc.AddHostResponse{}
|
||||
|
||||
err = client.Call("Urls.AddHost", req, resp)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Printf("Created host %s with token %s", resp.Hostname, resp.Token)
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
|
||||
"github.com/koding/tunnel"
|
||||
)
|
||||
|
||||
var (
|
||||
token = flag.String("token", "", "Service identifier token")
|
||||
backend = flag.String("backend", "127.0.0.1:9090", "backend TCP/HTTP server")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
cfg := &tunnel.ClientConfig{
|
||||
Identifier: *token,
|
||||
LocalAddr: *backend,
|
||||
ServerAddr: "127.0.0.1:9234",
|
||||
}
|
||||
|
||||
client, err := tunnel.NewClient(cfg)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
client.Start()
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/rpc"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.xeserv.us/xena/route/routerpc"
|
||||
|
||||
r "github.com/GoRethink/gorethink"
|
||||
"github.com/Xe/uuid"
|
||||
"github.com/Yawning/bulb"
|
||||
"github.com/facebookgo/flagenv"
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
"github.com/koding/tunnel"
|
||||
"github.com/sycamoreone/orc/tor"
|
||||
)
|
||||
|
||||
var (
|
||||
rethinkDBHost = flag.String("rethink-host", "", "RethinkDB host")
|
||||
rethinkDBDatabase = flag.String("rethink-database", "", "RethinkDB database")
|
||||
controlKeyFile = flag.String("control-key-file", "", "Control host keyfile")
|
||||
controlHost = flag.String("control-host", "", "Control host onion hash")
|
||||
torDataDir = flag.String("tor-data-dir", "./var", "Tor data directory")
|
||||
torHashedPassword = flag.String("tor-hashed-password", "", "Tor hashed password")
|
||||
torPassword = flag.String("tor-password", "hunter2", "Tor clear password")
|
||||
webPort = flag.String("web-port", "9234", "HTTP ingress port for backends and users")
|
||||
)
|
||||
|
||||
// RPC constants
|
||||
const (
|
||||
RPCPort uint16 = 39453
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
flagenv.Parse()
|
||||
rand.Seed(time.Now().Unix())
|
||||
|
||||
s, err := create(&ServerConfig{
|
||||
ControlHost: *controlHost,
|
||||
ControlKeyFile: *controlKeyFile,
|
||||
RethinkDBHost: *rethinkDBHost,
|
||||
RethinkDBDatabase: *rethinkDBDatabase,
|
||||
TorDataDir: *torDataDir,
|
||||
TorHashedPassword: *torHashedPassword,
|
||||
TorPassword: *torPassword,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
l, err := net.Listen("tcp", "127.0.0.1:"+*webPort)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer l.Close()
|
||||
|
||||
hs := &http.Server{
|
||||
Handler: s,
|
||||
Addr: "127.0.0.1:" + *webPort,
|
||||
}
|
||||
|
||||
hs.Serve(l)
|
||||
}
|
||||
|
||||
// Server is the main server type
|
||||
type Server struct {
|
||||
cfg *ServerConfig
|
||||
|
||||
sess *r.Session
|
||||
|
||||
torCon *bulb.Conn
|
||||
torCmd *tor.Cmd
|
||||
torControlPath string
|
||||
|
||||
rpcS *rpc.Server
|
||||
rpcAddr string
|
||||
|
||||
ts *tunnel.Server
|
||||
}
|
||||
|
||||
// ServerConfig configures Server
|
||||
type ServerConfig struct {
|
||||
ControlHost, ControlKeyFile string
|
||||
RethinkDBHost, RethinkDBDatabase string
|
||||
TorDataDir, TorHashedPassword, TorPassword string
|
||||
}
|
||||
|
||||
func create(cfg *ServerConfig) (*Server, error) {
|
||||
session, err := r.Connect(r.ConnectOpts{
|
||||
Address: cfg.RethinkDBHost,
|
||||
Database: cfg.RethinkDBDatabase,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
torControlPath := filepath.Join(cfg.TorDataDir, fmt.Sprintf("%d.sock", rand.Int63()))
|
||||
|
||||
tc := tor.NewConfig()
|
||||
tc.Set("ControlSocket", torControlPath)
|
||||
tc.Set("DataDirectory", cfg.TorDataDir)
|
||||
tc.Set("HashedControlPassword", cfg.TorHashedPassword)
|
||||
tc.Set("SocksPort", "0")
|
||||
cp := rand.Intn(64512) // 64k - 1k
|
||||
tc.Set("ControlPort", cp)
|
||||
|
||||
tc.Timeout = 30 * time.Second
|
||||
log.Println(tc.ToCmdLineFormat())
|
||||
|
||||
tcmd, err := tor.NewCmd(tc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = tcmd.Start()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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.TorPassword)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fin, err := os.Open(cfg.ControlKeyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer fin.Close()
|
||||
|
||||
data, err := ioutil.ReadAll(fin)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var block *pem.Block
|
||||
|
||||
block, _ = pem.Decode([]byte(data))
|
||||
pKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = bc.AddOnion([]bulb.OnionPortSpec{
|
||||
bulb.OnionPortSpec{
|
||||
VirtPort: RPCPort,
|
||||
Target: l.Addr().String(),
|
||||
},
|
||||
}, pKey, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rpcs := rpc.NewServer()
|
||||
|
||||
ts, err := tunnel.NewServer(&tunnel.ServerConfig{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := &Server{
|
||||
cfg: cfg,
|
||||
|
||||
sess: session,
|
||||
|
||||
torCon: bc,
|
||||
torCmd: tcmd,
|
||||
torControlPath: torControlPath,
|
||||
|
||||
rpcS: rpcs,
|
||||
rpcAddr: l.Addr().String(),
|
||||
|
||||
ts: ts,
|
||||
}
|
||||
|
||||
rpcs.RegisterName("Urls", &RPCServer{Server: s})
|
||||
go rpcs.Accept(l)
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *Server) onionPath(name string) string {
|
||||
return filepath.Join(s.cfg.TorDataDir, name)
|
||||
}
|
||||
|
||||
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if r.RequestURI == rpc.DefaultRPCPath {
|
||||
s.rpcS.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
s.ts.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
type RPCServer struct {
|
||||
*Server
|
||||
}
|
||||
|
||||
func (rs *RPCServer) AddHost(req routerpc.AddHostRequest, resp *routerpc.AddHostResponse) error {
|
||||
if req.APIKey != "hunter2" {
|
||||
return errors.New("invalid api key")
|
||||
}
|
||||
|
||||
token := uuid.New()
|
||||
|
||||
oi, err := rs.torCon.AddOnion([]bulb.OnionPortSpec{
|
||||
bulb.OnionPortSpec{
|
||||
VirtPort: 80,
|
||||
Target: "127.0.0.1:" + *webPort,
|
||||
},
|
||||
}, req.PrivKey, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resp.Hostname = oi.OnionID + ".onion"
|
||||
resp.Token = token
|
||||
|
||||
rs.Server.ts.AddHost(resp.Hostname, token)
|
||||
|
||||
if oi.PrivateKey != nil {
|
||||
resp.PrivKey = oi.PrivateKey
|
||||
} else {
|
||||
resp.PrivKey = req.PrivKey
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package routerpc
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rsa"
|
||||
"encoding/gob"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gob.Register(&AddHostRequest{})
|
||||
gob.Register(&AddHostResponse{})
|
||||
gob.Register(&rsa.PrivateKey{})
|
||||
}
|
||||
|
||||
// AddHostRequest is for adding a host to the routing mesh
|
||||
type AddHostRequest struct {
|
||||
APIKey string
|
||||
Hostname string
|
||||
PrivKey crypto.PrivateKey
|
||||
}
|
||||
|
||||
// AddHostResponse ...
|
||||
type AddHostResponse struct {
|
||||
Token string
|
||||
Hostname string
|
||||
PrivKey crypto.PrivateKey
|
||||
}
|
Loading…
Reference in New Issue