Move things around, set up a more structured app
This commit is contained in:
parent
bde3d7da90
commit
f7df55f044
|
@ -0,0 +1,10 @@
|
||||||
|
route
|
||||||
|
=====
|
||||||
|
|
||||||
|
A simple cluster-friendly load balancer for singleton microservices.
|
||||||
|
|
||||||
|
TODO
|
||||||
|
----
|
||||||
|
|
||||||
|
- [ ] Store stuff into RethinkDB
|
||||||
|
- [ ] Add Let's Encrypt support in addition to a free tor hidden service with every domain routed
|
|
@ -0,0 +1,80 @@
|
||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
|
||||||
|
"git.xeserv.us/xena/route/routerpc"
|
||||||
|
r "github.com/GoRethink/gorethink"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DB struct {
|
||||||
|
s *r.Session
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(host, database string) (*DB, error) {
|
||||||
|
session, err := r.Connect(r.ConnectOpts{
|
||||||
|
Address: host,
|
||||||
|
Database: database,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
db := &DB{
|
||||||
|
s: session,
|
||||||
|
}
|
||||||
|
|
||||||
|
return db, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var tables = []string{
|
||||||
|
"certs",
|
||||||
|
"routes",
|
||||||
|
}
|
||||||
|
|
||||||
|
type Route struct {
|
||||||
|
ID string `gorethink:"id,omitempty"`
|
||||||
|
Hostname string `gorethink:"hostname"`
|
||||||
|
OnionHostname string `gorethink:"onionhostname"`
|
||||||
|
Token string `gorethink:"token"`
|
||||||
|
OnionKey []byte `gorethink:"onionKey"` // PEM-encoded
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) SaveRoute(resp *routerpc.AddHostResponse) error {
|
||||||
|
pemblock := &pem.Block{
|
||||||
|
Type: "RSA PRIVATE KEY",
|
||||||
|
Bytes: x509.MarshalPKCS1PrivateKey(resp.PrivKey.(*rsa.PrivateKey)),
|
||||||
|
}
|
||||||
|
bytes := pem.EncodeToMemory(pemblock)
|
||||||
|
|
||||||
|
rt := &Route{
|
||||||
|
Hostname: resp.Hostname,
|
||||||
|
OnionHostname: resp.OnionHostname,
|
||||||
|
Token: resp.Token,
|
||||||
|
OnionKey: bytes,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := r.Table("routes").Insert(rt).RunWrite(db.s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *DB) GetAllRoutes() ([]Route, error) {
|
||||||
|
rows, err := r.Table("routes").Run(db.s)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var routes []Route
|
||||||
|
err = rows.All(&routes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return routes, nil
|
||||||
|
}
|
|
@ -0,0 +1,505 @@
|
||||||
|
/*
|
||||||
|
Package elfs is this project's heroku style name generator.
|
||||||
|
*/
|
||||||
|
package elfs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Names is the name of every Pokemon from Pokemon Vietnamese Crystal.
|
||||||
|
var Names = []string{
|
||||||
|
"SEED",
|
||||||
|
"GRASS",
|
||||||
|
"FLOWE",
|
||||||
|
"SHAD",
|
||||||
|
"CABR",
|
||||||
|
"SNAKE",
|
||||||
|
"GOLD",
|
||||||
|
"COW",
|
||||||
|
"GUIKI",
|
||||||
|
"PEDAL",
|
||||||
|
"DELAN",
|
||||||
|
"B-FLY",
|
||||||
|
"BIDE",
|
||||||
|
"KEYU",
|
||||||
|
"FORK",
|
||||||
|
"LAP",
|
||||||
|
"PIGE",
|
||||||
|
"PIJIA",
|
||||||
|
"CAML",
|
||||||
|
"LAT",
|
||||||
|
"BIRD",
|
||||||
|
"BABOO",
|
||||||
|
"VIV",
|
||||||
|
"ABOKE",
|
||||||
|
"PIKAQ",
|
||||||
|
"RYE",
|
||||||
|
"SAN",
|
||||||
|
"BREAD",
|
||||||
|
"LIDEL",
|
||||||
|
"LIDE",
|
||||||
|
"PIP",
|
||||||
|
"PIKEX",
|
||||||
|
"ROK",
|
||||||
|
"JUGEN",
|
||||||
|
"PUD",
|
||||||
|
"BUDE",
|
||||||
|
"ZHIB",
|
||||||
|
"GELU",
|
||||||
|
"GRAS",
|
||||||
|
"FLOW",
|
||||||
|
"LAFUL",
|
||||||
|
"ATH",
|
||||||
|
"BALA",
|
||||||
|
"CORN",
|
||||||
|
"MOLUF",
|
||||||
|
"DESP",
|
||||||
|
"DAKED",
|
||||||
|
"MIMI",
|
||||||
|
"BOLUX",
|
||||||
|
"KODA",
|
||||||
|
"GELUD",
|
||||||
|
"MONK",
|
||||||
|
"SUMOY",
|
||||||
|
"GEDI",
|
||||||
|
"WENDI",
|
||||||
|
"NILEM",
|
||||||
|
"NILE",
|
||||||
|
"NILEC",
|
||||||
|
"KEZI",
|
||||||
|
"YONGL",
|
||||||
|
"HUDE",
|
||||||
|
"WANLI",
|
||||||
|
"GELI",
|
||||||
|
"GUAIL",
|
||||||
|
"MADAQ",
|
||||||
|
"WUCI",
|
||||||
|
"WUCI",
|
||||||
|
"MUJEF",
|
||||||
|
"JELLY",
|
||||||
|
"SICIB",
|
||||||
|
"GELU",
|
||||||
|
"NELUO",
|
||||||
|
"BOLI",
|
||||||
|
"JIALE",
|
||||||
|
"YED",
|
||||||
|
"YEDE",
|
||||||
|
"CLO",
|
||||||
|
"SCARE",
|
||||||
|
"AOCO",
|
||||||
|
"DEDE",
|
||||||
|
"DEDEI",
|
||||||
|
"BAWU",
|
||||||
|
"JIUG",
|
||||||
|
"BADEB",
|
||||||
|
"BADEB",
|
||||||
|
"HOLE",
|
||||||
|
"BALUX",
|
||||||
|
"GES",
|
||||||
|
"FANT",
|
||||||
|
"QUAR",
|
||||||
|
"YIHE",
|
||||||
|
"SWAB",
|
||||||
|
"SLIPP",
|
||||||
|
"CLU",
|
||||||
|
"DEPOS",
|
||||||
|
"BILIY",
|
||||||
|
"YUANO",
|
||||||
|
"SOME",
|
||||||
|
"NO",
|
||||||
|
"YELA",
|
||||||
|
"EMPT",
|
||||||
|
"ZECUN",
|
||||||
|
"XIAHE",
|
||||||
|
"BOLEL",
|
||||||
|
"DEJI",
|
||||||
|
"MACID",
|
||||||
|
"XIHON",
|
||||||
|
"XITO",
|
||||||
|
"LUCK",
|
||||||
|
"MENJI",
|
||||||
|
"GELU",
|
||||||
|
"DECI",
|
||||||
|
"XIDE",
|
||||||
|
"DASAJ",
|
||||||
|
"DONGN",
|
||||||
|
"RICUL",
|
||||||
|
"MINXI",
|
||||||
|
"BALIY",
|
||||||
|
"ZENDA",
|
||||||
|
"LUZEL",
|
||||||
|
"HELE5",
|
||||||
|
"0FENB",
|
||||||
|
"KAIL",
|
||||||
|
"JIAND",
|
||||||
|
"CARP",
|
||||||
|
"JINDE",
|
||||||
|
"LAPU",
|
||||||
|
"MUDE",
|
||||||
|
"YIFU",
|
||||||
|
"LINLI",
|
||||||
|
"SANDI",
|
||||||
|
"HUSI",
|
||||||
|
"JINC",
|
||||||
|
"OUMU",
|
||||||
|
"OUMUX",
|
||||||
|
"CAP",
|
||||||
|
"KUIZA",
|
||||||
|
"PUD",
|
||||||
|
"TIAO",
|
||||||
|
"FRMAN",
|
||||||
|
"CLAU",
|
||||||
|
"SPARK",
|
||||||
|
"DRAGO",
|
||||||
|
"BOLIU",
|
||||||
|
"GUAIL",
|
||||||
|
"MIYOU",
|
||||||
|
"MIY",
|
||||||
|
"QIAOK",
|
||||||
|
"BEIL",
|
||||||
|
"MUKEI",
|
||||||
|
"RIDED",
|
||||||
|
"MADAM",
|
||||||
|
"BAGEP",
|
||||||
|
"CROC",
|
||||||
|
"ALIGE",
|
||||||
|
"OUDAL",
|
||||||
|
"OUD",
|
||||||
|
"DADA",
|
||||||
|
"HEHE",
|
||||||
|
"YEDEA",
|
||||||
|
"NUXI",
|
||||||
|
"NUXIN",
|
||||||
|
"ROUY",
|
||||||
|
"ALIAD",
|
||||||
|
"STICK",
|
||||||
|
"QIANG",
|
||||||
|
"LAAND",
|
||||||
|
"PIQI",
|
||||||
|
"PI",
|
||||||
|
"PUPI",
|
||||||
|
"DEKE",
|
||||||
|
"DEKEJ",
|
||||||
|
"NADI",
|
||||||
|
"NADIO",
|
||||||
|
"MALI",
|
||||||
|
"PEA",
|
||||||
|
"ELECT",
|
||||||
|
"FLOWE",
|
||||||
|
"MAL",
|
||||||
|
"MALI",
|
||||||
|
"HUSHU",
|
||||||
|
"NILEE",
|
||||||
|
"YUZI",
|
||||||
|
"POPOZ",
|
||||||
|
"DUZI",
|
||||||
|
"HEBA",
|
||||||
|
"XIAN",
|
||||||
|
"SHAN",
|
||||||
|
"YEYEA",
|
||||||
|
"WUY",
|
||||||
|
"LUO",
|
||||||
|
"KEFE",
|
||||||
|
"HULA",
|
||||||
|
"CROW",
|
||||||
|
"YADEH",
|
||||||
|
"MOW",
|
||||||
|
"ANNAN",
|
||||||
|
"SUONI",
|
||||||
|
"KYLI",
|
||||||
|
"HULU",
|
||||||
|
"HUDEL",
|
||||||
|
"YEHE",
|
||||||
|
"GULAE",
|
||||||
|
"YEHE",
|
||||||
|
"BLU",
|
||||||
|
"GELAN",
|
||||||
|
"BOAT",
|
||||||
|
"NIP",
|
||||||
|
"POIT",
|
||||||
|
"HELAK",
|
||||||
|
"XINL",
|
||||||
|
"BEAR",
|
||||||
|
"LINB",
|
||||||
|
"MAGEH",
|
||||||
|
"MAGEJ",
|
||||||
|
"WULI",
|
||||||
|
"YIDE",
|
||||||
|
"RIVE",
|
||||||
|
"FISH",
|
||||||
|
"AOGU",
|
||||||
|
"DELIE",
|
||||||
|
"MANTE",
|
||||||
|
"KONMU",
|
||||||
|
"DELU",
|
||||||
|
"HELU",
|
||||||
|
"HUAN",
|
||||||
|
"HUMA",
|
||||||
|
"DONGF",
|
||||||
|
"JINCA",
|
||||||
|
"HEDE",
|
||||||
|
"DEFU",
|
||||||
|
"LIBY",
|
||||||
|
"JIAPA",
|
||||||
|
"MEJI",
|
||||||
|
"HELE",
|
||||||
|
"BUHU",
|
||||||
|
"MILK",
|
||||||
|
"HABI",
|
||||||
|
"THUN",
|
||||||
|
"GARD",
|
||||||
|
"DON",
|
||||||
|
"YANGQ",
|
||||||
|
"SANAQ",
|
||||||
|
"BANQ",
|
||||||
|
"LUJ",
|
||||||
|
"PHIX",
|
||||||
|
"SIEI",
|
||||||
|
"EGG",
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moves is every single move from Pokemon Vietnamese Crystal.
|
||||||
|
var Moves = []string{
|
||||||
|
"ABLE",
|
||||||
|
"ABNORMA",
|
||||||
|
"AGAIN",
|
||||||
|
"AIREXPL",
|
||||||
|
"ANG",
|
||||||
|
"ANGER",
|
||||||
|
"ASAIL",
|
||||||
|
"ATTACK",
|
||||||
|
"AURORA",
|
||||||
|
"AWL",
|
||||||
|
"BAN",
|
||||||
|
"BAND",
|
||||||
|
"BARE",
|
||||||
|
"BEAT",
|
||||||
|
"BEATED",
|
||||||
|
"BELLY",
|
||||||
|
"BIND",
|
||||||
|
"BITE",
|
||||||
|
"BLOC",
|
||||||
|
"BLOOD",
|
||||||
|
"BODY",
|
||||||
|
"BOOK",
|
||||||
|
"BREATH",
|
||||||
|
"BUMP",
|
||||||
|
"CAST",
|
||||||
|
"CHAM",
|
||||||
|
"CLAMP",
|
||||||
|
"CLAP",
|
||||||
|
"CLAW",
|
||||||
|
"CLEAR",
|
||||||
|
"CLI",
|
||||||
|
"CLIP",
|
||||||
|
"CLOUD",
|
||||||
|
"CONTRO",
|
||||||
|
"CONVY",
|
||||||
|
"COOLHIT",
|
||||||
|
"CRASH",
|
||||||
|
"CRY",
|
||||||
|
"CUT",
|
||||||
|
"DESCRI",
|
||||||
|
"D-FIGHT",
|
||||||
|
"DIG",
|
||||||
|
"DITCH",
|
||||||
|
"DIV",
|
||||||
|
"DOZ",
|
||||||
|
"DRE",
|
||||||
|
"DUL",
|
||||||
|
"DU-PIN",
|
||||||
|
"DYE",
|
||||||
|
"EARTH",
|
||||||
|
"EDU",
|
||||||
|
"EG-BOMB",
|
||||||
|
"EGG",
|
||||||
|
"ELEGY",
|
||||||
|
"ELE-HIT",
|
||||||
|
"EMBODY",
|
||||||
|
"EMPLI",
|
||||||
|
"ENGL",
|
||||||
|
"ERUPT",
|
||||||
|
"EVENS",
|
||||||
|
"EXPLOR",
|
||||||
|
"EYES",
|
||||||
|
"FALL",
|
||||||
|
"FAST",
|
||||||
|
"F-CAR",
|
||||||
|
"F-DANCE",
|
||||||
|
"FEARS",
|
||||||
|
"F-FIGHT",
|
||||||
|
"FIGHT",
|
||||||
|
"FIR",
|
||||||
|
"FIRE",
|
||||||
|
"FIREHIT",
|
||||||
|
"FLAME",
|
||||||
|
"FLAP",
|
||||||
|
"FLASH",
|
||||||
|
"FLEW",
|
||||||
|
"FORCE",
|
||||||
|
"FRA",
|
||||||
|
"FREEZE",
|
||||||
|
"FROG",
|
||||||
|
"G-BIRD",
|
||||||
|
"GENKISS",
|
||||||
|
"GIFT",
|
||||||
|
"G-KISS",
|
||||||
|
"G-MOUSE",
|
||||||
|
"GRADE",
|
||||||
|
"GROW",
|
||||||
|
"HAMMER",
|
||||||
|
"HARD",
|
||||||
|
"HAT",
|
||||||
|
"HATE",
|
||||||
|
"H-BOMB",
|
||||||
|
"HELL-R",
|
||||||
|
"HEMP",
|
||||||
|
"HINT",
|
||||||
|
"HIT",
|
||||||
|
"HU",
|
||||||
|
"HUNT",
|
||||||
|
"HYPNOSI",
|
||||||
|
"INHA",
|
||||||
|
"IRO",
|
||||||
|
"IRONBAR",
|
||||||
|
"IR-WING",
|
||||||
|
"J-GUN",
|
||||||
|
"KEE",
|
||||||
|
"KICK",
|
||||||
|
"KNIF",
|
||||||
|
"KNIFE",
|
||||||
|
"KNOCK",
|
||||||
|
"LEVEL",
|
||||||
|
"LIGH",
|
||||||
|
"LIGHHIT",
|
||||||
|
"LIGHT",
|
||||||
|
"LIVE",
|
||||||
|
"L-WALL",
|
||||||
|
"MAD",
|
||||||
|
"MAJUS",
|
||||||
|
"MEL",
|
||||||
|
"MELO",
|
||||||
|
"MESS",
|
||||||
|
"MILK",
|
||||||
|
"MIMI",
|
||||||
|
"MISS",
|
||||||
|
"MIXING",
|
||||||
|
"MOVE",
|
||||||
|
"MUD",
|
||||||
|
"NI-BED",
|
||||||
|
"NOISY",
|
||||||
|
"NOONLI",
|
||||||
|
"NULL",
|
||||||
|
"N-WAVE",
|
||||||
|
"PAT",
|
||||||
|
"PEACE",
|
||||||
|
"PIN",
|
||||||
|
"PLAN",
|
||||||
|
"PLANE",
|
||||||
|
"POIS",
|
||||||
|
"POL",
|
||||||
|
"POWDE",
|
||||||
|
"POWE",
|
||||||
|
"POWER",
|
||||||
|
"PRIZE",
|
||||||
|
"PROTECT",
|
||||||
|
"PROUD",
|
||||||
|
"RAGE",
|
||||||
|
"RECOR",
|
||||||
|
"REFLAC",
|
||||||
|
"REFREC",
|
||||||
|
"REGR",
|
||||||
|
"RELIV",
|
||||||
|
"RENEW",
|
||||||
|
"R-FIGHT",
|
||||||
|
"RING",
|
||||||
|
"RKICK",
|
||||||
|
"ROCK",
|
||||||
|
"ROUND",
|
||||||
|
"RUS",
|
||||||
|
"RUSH",
|
||||||
|
"SAND",
|
||||||
|
"SAW",
|
||||||
|
"SCISSOR",
|
||||||
|
"SCRA",
|
||||||
|
"SCRIPT",
|
||||||
|
"SEEN",
|
||||||
|
"SERVER",
|
||||||
|
"SHADOW",
|
||||||
|
"SHELL",
|
||||||
|
"SHINE",
|
||||||
|
"SHO",
|
||||||
|
"SIGHT",
|
||||||
|
"SIN",
|
||||||
|
"SMALL",
|
||||||
|
"SMELT",
|
||||||
|
"SMOK",
|
||||||
|
"SNAKE",
|
||||||
|
"SNO",
|
||||||
|
"SNOW",
|
||||||
|
"SOU",
|
||||||
|
"SO-WAVE",
|
||||||
|
"SPAR",
|
||||||
|
"SPEC",
|
||||||
|
"SPID",
|
||||||
|
"S-PIN",
|
||||||
|
"SPRA",
|
||||||
|
"STAM",
|
||||||
|
"STARE",
|
||||||
|
"STEA",
|
||||||
|
"STONE",
|
||||||
|
"STORM",
|
||||||
|
"STRU",
|
||||||
|
"STRUG",
|
||||||
|
"STUDEN",
|
||||||
|
"SUBS",
|
||||||
|
"SUCID",
|
||||||
|
"SUN-LIG",
|
||||||
|
"SUNRIS",
|
||||||
|
"SUPLY",
|
||||||
|
"S-WAVE",
|
||||||
|
"TAILS",
|
||||||
|
"TANGL",
|
||||||
|
"TASTE",
|
||||||
|
"TELLI",
|
||||||
|
"THANK",
|
||||||
|
"TONKICK",
|
||||||
|
"TOOTH",
|
||||||
|
"TORL",
|
||||||
|
"TRAIN",
|
||||||
|
"TRIKICK",
|
||||||
|
"TUNGE",
|
||||||
|
"VOLT",
|
||||||
|
"WA-GUN",
|
||||||
|
"WATCH",
|
||||||
|
"WAVE",
|
||||||
|
"W-BOMB",
|
||||||
|
"WFALL",
|
||||||
|
"WFING",
|
||||||
|
"WHIP",
|
||||||
|
"WHIRL",
|
||||||
|
"WIND",
|
||||||
|
"WOLF",
|
||||||
|
"WOOD",
|
||||||
|
"WOR",
|
||||||
|
"YUJA",
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomMove() string {
|
||||||
|
return Moves[rand.Intn(len(Moves))]
|
||||||
|
}
|
||||||
|
|
||||||
|
func randomName() string {
|
||||||
|
return Names[rand.Intn(len(Names))]
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeName generates a new domain name based on the moves and Pokemon names
|
||||||
|
// from Pokemon Vietnamese Crystal.
|
||||||
|
func MakeName() string {
|
||||||
|
move1 := randomMove()
|
||||||
|
move2 := randomMove()
|
||||||
|
poke := randomName()
|
||||||
|
return fmt.Sprintf("%s-%s-%s", move1, move2, poke)
|
||||||
|
}
|
|
@ -0,0 +1,225 @@
|
||||||
|
{
|
||||||
|
"ABLE",
|
||||||
|
"ABNORMA",
|
||||||
|
"AGAIN",
|
||||||
|
"AIREXPL",
|
||||||
|
"ANG",
|
||||||
|
"ANGER",
|
||||||
|
"ASAIL",
|
||||||
|
"ATTACK",
|
||||||
|
"AURORA",
|
||||||
|
"AWL",
|
||||||
|
"BAN",
|
||||||
|
"BAND",
|
||||||
|
"BARE",
|
||||||
|
"BEAT",
|
||||||
|
"BEATED",
|
||||||
|
"BELLY",
|
||||||
|
"BIND",
|
||||||
|
"BITE",
|
||||||
|
"BLOC",
|
||||||
|
"BLOOD",
|
||||||
|
"BODY",
|
||||||
|
"BOOK",
|
||||||
|
"BREATH",
|
||||||
|
"BUMP",
|
||||||
|
"CAST",
|
||||||
|
"CHAM",
|
||||||
|
"CLAMP",
|
||||||
|
"CLAP",
|
||||||
|
"CLAW",
|
||||||
|
"CLEAR",
|
||||||
|
"CLI",
|
||||||
|
"CLIP",
|
||||||
|
"CLOUD",
|
||||||
|
"CONTRO",
|
||||||
|
"CONVY",
|
||||||
|
"COOLHIT",
|
||||||
|
"CRASH",
|
||||||
|
"CRY",
|
||||||
|
"CUT",
|
||||||
|
"DESCRI",
|
||||||
|
"D-FIGHT",
|
||||||
|
"DIG",
|
||||||
|
"DITCH",
|
||||||
|
"DIV",
|
||||||
|
"DOZ",
|
||||||
|
"DRE",
|
||||||
|
"DUL",
|
||||||
|
"DU-PIN",
|
||||||
|
"DYE",
|
||||||
|
"EARTH",
|
||||||
|
"EDU",
|
||||||
|
"EG-BOMB",
|
||||||
|
"EGG",
|
||||||
|
"ELEGY",
|
||||||
|
"ELE-HIT",
|
||||||
|
"EMBODY",
|
||||||
|
"EMPLI",
|
||||||
|
"ENGL",
|
||||||
|
"ERUPT",
|
||||||
|
"EVENS",
|
||||||
|
"EXPLOR",
|
||||||
|
"EYES",
|
||||||
|
"FALL",
|
||||||
|
"FAST",
|
||||||
|
"F-CAR",
|
||||||
|
"F-DANCE",
|
||||||
|
"FEARS",
|
||||||
|
"F-FIGHT",
|
||||||
|
"FIGHT",
|
||||||
|
"FIR",
|
||||||
|
"FIRE",
|
||||||
|
"FIREHIT",
|
||||||
|
"FLAME",
|
||||||
|
"FLAP",
|
||||||
|
"FLASH",
|
||||||
|
"FLEW",
|
||||||
|
"FORCE",
|
||||||
|
"FRA",
|
||||||
|
"FREEZE",
|
||||||
|
"FROG",
|
||||||
|
"G-BIRD",
|
||||||
|
"GENKISS",
|
||||||
|
"GIFT",
|
||||||
|
"G-KISS",
|
||||||
|
"G-MOUSE",
|
||||||
|
"GRADE",
|
||||||
|
"GROW",
|
||||||
|
"HAMMER",
|
||||||
|
"HARD",
|
||||||
|
"HAT",
|
||||||
|
"HATE",
|
||||||
|
"H-BOMB",
|
||||||
|
"HELL-R",
|
||||||
|
"HEMP",
|
||||||
|
"HINT",
|
||||||
|
"HIT",
|
||||||
|
"HU",
|
||||||
|
"HUNT",
|
||||||
|
"HYPNOSI",
|
||||||
|
"INHA",
|
||||||
|
"IRO",
|
||||||
|
"IRONBAR",
|
||||||
|
"IR-WING",
|
||||||
|
"J-GUN",
|
||||||
|
"KEE",
|
||||||
|
"KICK",
|
||||||
|
"KNIF",
|
||||||
|
"KNIFE",
|
||||||
|
"KNOCK",
|
||||||
|
"LEVEL",
|
||||||
|
"LIGH",
|
||||||
|
"LIGHHIT",
|
||||||
|
"LIGHT",
|
||||||
|
"LIVE",
|
||||||
|
"L-WALL",
|
||||||
|
"MAD",
|
||||||
|
"MAJUS",
|
||||||
|
"MEL",
|
||||||
|
"MELO",
|
||||||
|
"MESS",
|
||||||
|
"MILK",
|
||||||
|
"MIMI",
|
||||||
|
"MISS",
|
||||||
|
"MIXING",
|
||||||
|
"MOVE",
|
||||||
|
"MUD",
|
||||||
|
"NI-BED",
|
||||||
|
"NOISY",
|
||||||
|
"NOONLI",
|
||||||
|
"NULL",
|
||||||
|
"N-WAVE",
|
||||||
|
"PAT",
|
||||||
|
"PEACE",
|
||||||
|
"PIN",
|
||||||
|
"PLAN",
|
||||||
|
"PLANE",
|
||||||
|
"POIS",
|
||||||
|
"POL",
|
||||||
|
"POWDE",
|
||||||
|
"POWE",
|
||||||
|
"POWER",
|
||||||
|
"PRIZE",
|
||||||
|
"PROTECT",
|
||||||
|
"PROUD",
|
||||||
|
"RAGE",
|
||||||
|
"RECOR",
|
||||||
|
"REFLAC",
|
||||||
|
"REFREC",
|
||||||
|
"REGR",
|
||||||
|
"RELIV",
|
||||||
|
"RENEW",
|
||||||
|
"R-FIGHT",
|
||||||
|
"RING",
|
||||||
|
"RKICK",
|
||||||
|
"ROCK",
|
||||||
|
"ROUND",
|
||||||
|
"RUS",
|
||||||
|
"RUSH",
|
||||||
|
"SAND",
|
||||||
|
"SAW",
|
||||||
|
"SCISSOR",
|
||||||
|
"SCRA",
|
||||||
|
"SCRIPT",
|
||||||
|
"SEEN",
|
||||||
|
"SERVER",
|
||||||
|
"SHADOW",
|
||||||
|
"SHELL",
|
||||||
|
"SHINE",
|
||||||
|
"SHO",
|
||||||
|
"SIGHT",
|
||||||
|
"SIN",
|
||||||
|
"SMALL",
|
||||||
|
"SMELT",
|
||||||
|
"SMOK",
|
||||||
|
"SNAKE",
|
||||||
|
"SNO",
|
||||||
|
"SNOW",
|
||||||
|
"SOU",
|
||||||
|
"SO-WAVE",
|
||||||
|
"SPAR",
|
||||||
|
"SPEC",
|
||||||
|
"SPID",
|
||||||
|
"S-PIN",
|
||||||
|
"SPRA",
|
||||||
|
"STAM",
|
||||||
|
"STARE",
|
||||||
|
"STEA",
|
||||||
|
"STONE",
|
||||||
|
"STORM",
|
||||||
|
"STRU",
|
||||||
|
"STRUG",
|
||||||
|
"STUDEN",
|
||||||
|
"SUBS",
|
||||||
|
"SUCID",
|
||||||
|
"SUN-LIG",
|
||||||
|
"SUNRIS",
|
||||||
|
"SUPLY",
|
||||||
|
"S-WAVE",
|
||||||
|
"TAILS",
|
||||||
|
"TANGL",
|
||||||
|
"TASTE",
|
||||||
|
"TELLI",
|
||||||
|
"THANK",
|
||||||
|
"TONKICK",
|
||||||
|
"TOOTH",
|
||||||
|
"TORL",
|
||||||
|
"TRAIN",
|
||||||
|
"TRIKICK",
|
||||||
|
"TUNGE",
|
||||||
|
"VOLT",
|
||||||
|
"WA-GUN",
|
||||||
|
"WATCH",
|
||||||
|
"WAVE",
|
||||||
|
"W-BOMB",
|
||||||
|
"WFALL",
|
||||||
|
"WFING",
|
||||||
|
"WHIP",
|
||||||
|
"WHIRL",
|
||||||
|
"WIND",
|
||||||
|
"WOLF",
|
||||||
|
"WOOD",
|
||||||
|
"WOR",
|
||||||
|
"YUJA",
|
||||||
|
}
|
|
@ -0,0 +1,250 @@
|
||||||
|
{
|
||||||
|
"SEED",
|
||||||
|
"GRASS",
|
||||||
|
"FLOWE",
|
||||||
|
"SHAD",
|
||||||
|
"CABR",
|
||||||
|
"SNAKE",
|
||||||
|
"GOLD",
|
||||||
|
"COW",
|
||||||
|
"GUIKI",
|
||||||
|
"PEDAL",
|
||||||
|
"DELAN",
|
||||||
|
"B-FLY",
|
||||||
|
"BIDE",
|
||||||
|
"KEYU",
|
||||||
|
"FORK",
|
||||||
|
"LAP",
|
||||||
|
"PIGE",
|
||||||
|
"PIJIA",
|
||||||
|
"CAML",
|
||||||
|
"LAT",
|
||||||
|
"BIRD",
|
||||||
|
"BABOO",
|
||||||
|
"VIV",
|
||||||
|
"ABOKE",
|
||||||
|
"PIKAQ",
|
||||||
|
"RYE",
|
||||||
|
"SAN",
|
||||||
|
"BREAD",
|
||||||
|
"LIDEL",
|
||||||
|
"LIDE",
|
||||||
|
"PIP",
|
||||||
|
"PIKEX",
|
||||||
|
"ROK",
|
||||||
|
"JUGEN",
|
||||||
|
"PUD",
|
||||||
|
"BUDE",
|
||||||
|
"ZHIB",
|
||||||
|
"GELU",
|
||||||
|
"GRAS",
|
||||||
|
"FLOW",
|
||||||
|
"LAFUL",
|
||||||
|
"ATH",
|
||||||
|
"BALA",
|
||||||
|
"CORN",
|
||||||
|
"MOLUF",
|
||||||
|
"DESP",
|
||||||
|
"DAKED",
|
||||||
|
"MIMI",
|
||||||
|
"BOLUX",
|
||||||
|
"KODA",
|
||||||
|
"GELUD",
|
||||||
|
"MONK",
|
||||||
|
"SUMOY",
|
||||||
|
"GEDI",
|
||||||
|
"WENDI",
|
||||||
|
"NILEM",
|
||||||
|
"NILE",
|
||||||
|
"NILEC",
|
||||||
|
"KEZI",
|
||||||
|
"YONGL",
|
||||||
|
"HUDE",
|
||||||
|
"WANLI",
|
||||||
|
"GELI",
|
||||||
|
"GUAIL",
|
||||||
|
"MADAQ",
|
||||||
|
"WUCI",
|
||||||
|
"WUCI",
|
||||||
|
"MUJEF",
|
||||||
|
"JELLY",
|
||||||
|
"SICIB",
|
||||||
|
"GELU",
|
||||||
|
"NELUO",
|
||||||
|
"BOLI",
|
||||||
|
"JIALE",
|
||||||
|
"YED",
|
||||||
|
"YEDE",
|
||||||
|
"CLO",
|
||||||
|
"SCARE",
|
||||||
|
"AOCO",
|
||||||
|
"DEDE",
|
||||||
|
"DEDEI",
|
||||||
|
"BAWU",
|
||||||
|
"JIUG",
|
||||||
|
"BADEB",
|
||||||
|
"BADEB",
|
||||||
|
"HOLE",
|
||||||
|
"BALUX",
|
||||||
|
"GES",
|
||||||
|
"FANT",
|
||||||
|
"QUAR",
|
||||||
|
"YIHE",
|
||||||
|
"SWAB",
|
||||||
|
"SLIPP",
|
||||||
|
"CLU",
|
||||||
|
"DEPOS",
|
||||||
|
"BILIY",
|
||||||
|
"YUANO",
|
||||||
|
"SOME",
|
||||||
|
"NO",
|
||||||
|
"YELA",
|
||||||
|
"EMPT",
|
||||||
|
"ZECUN",
|
||||||
|
"XIAHE",
|
||||||
|
"BOLEL",
|
||||||
|
"DEJI",
|
||||||
|
"MACID",
|
||||||
|
"XIHON",
|
||||||
|
"XITO",
|
||||||
|
"LUCK",
|
||||||
|
"MENJI",
|
||||||
|
"GELU",
|
||||||
|
"DECI",
|
||||||
|
"XIDE",
|
||||||
|
"DASAJ",
|
||||||
|
"DONGN",
|
||||||
|
"RICUL",
|
||||||
|
"MINXI",
|
||||||
|
"BALIY",
|
||||||
|
"ZENDA",
|
||||||
|
"LUZEL",
|
||||||
|
"HELE5",
|
||||||
|
"0FENB",
|
||||||
|
"KAIL",
|
||||||
|
"JIAND",
|
||||||
|
"CARP",
|
||||||
|
"JINDE",
|
||||||
|
"LAPU",
|
||||||
|
"MUDE",
|
||||||
|
"YIFU",
|
||||||
|
"LINLI",
|
||||||
|
"SANDI",
|
||||||
|
"HUSI",
|
||||||
|
"JINC",
|
||||||
|
"OUMU",
|
||||||
|
"OUMUX",
|
||||||
|
"CAP",
|
||||||
|
"KUIZA",
|
||||||
|
"PUD",
|
||||||
|
"TIAO",
|
||||||
|
"FRMAN",
|
||||||
|
"CLAU",
|
||||||
|
"SPARK",
|
||||||
|
"DRAGO",
|
||||||
|
"BOLIU",
|
||||||
|
"GUAIL",
|
||||||
|
"MIYOU",
|
||||||
|
"MIY",
|
||||||
|
"QIAOK",
|
||||||
|
"BEIL",
|
||||||
|
"MUKEI",
|
||||||
|
"RIDED",
|
||||||
|
"MADAM",
|
||||||
|
"BAGEP",
|
||||||
|
"CROC",
|
||||||
|
"ALIGE",
|
||||||
|
"OUDAL",
|
||||||
|
"OUD",
|
||||||
|
"DADA",
|
||||||
|
"HEHE",
|
||||||
|
"YEDEA",
|
||||||
|
"NUXI",
|
||||||
|
"NUXIN",
|
||||||
|
"ROUY",
|
||||||
|
"ALIAD",
|
||||||
|
"STICK",
|
||||||
|
"QIANG",
|
||||||
|
"LAAND",
|
||||||
|
"PIQI",
|
||||||
|
"PI",
|
||||||
|
"PUPI",
|
||||||
|
"DEKE",
|
||||||
|
"DEKEJ",
|
||||||
|
"NADI",
|
||||||
|
"NADIO",
|
||||||
|
"MALI",
|
||||||
|
"PEA",
|
||||||
|
"ELECT",
|
||||||
|
"FLOWE",
|
||||||
|
"MAL",
|
||||||
|
"MALI",
|
||||||
|
"HUSHU",
|
||||||
|
"NILEE",
|
||||||
|
"YUZI",
|
||||||
|
"POPOZ",
|
||||||
|
"DUZI",
|
||||||
|
"HEBA",
|
||||||
|
"XIAN",
|
||||||
|
"SHAN",
|
||||||
|
"YEYEA",
|
||||||
|
"WUY",
|
||||||
|
"LUO",
|
||||||
|
"KEFE",
|
||||||
|
"HULA",
|
||||||
|
"CROW",
|
||||||
|
"YADEH",
|
||||||
|
"MOW",
|
||||||
|
"ANNAN",
|
||||||
|
"SUONI",
|
||||||
|
"KYLI",
|
||||||
|
"HULU",
|
||||||
|
"HUDEL",
|
||||||
|
"YEHE",
|
||||||
|
"GULAE",
|
||||||
|
"YEHE",
|
||||||
|
"BLU",
|
||||||
|
"GELAN",
|
||||||
|
"BOAT",
|
||||||
|
"NIP",
|
||||||
|
"POIT",
|
||||||
|
"HELAK",
|
||||||
|
"XINL",
|
||||||
|
"BEAR",
|
||||||
|
"LINB",
|
||||||
|
"MAGEH",
|
||||||
|
"MAGEJ",
|
||||||
|
"WULI",
|
||||||
|
"YIDE",
|
||||||
|
"RIVE",
|
||||||
|
"FISH",
|
||||||
|
"AOGU",
|
||||||
|
"DELIE",
|
||||||
|
"MANTE",
|
||||||
|
"KONMU",
|
||||||
|
"DELU",
|
||||||
|
"HELU",
|
||||||
|
"HUAN",
|
||||||
|
"HUMA",
|
||||||
|
"DONGF",
|
||||||
|
"JINCA",
|
||||||
|
"HEDE",
|
||||||
|
"DEFU",
|
||||||
|
"LIBY",
|
||||||
|
"JIAPA",
|
||||||
|
"MEJI",
|
||||||
|
"HELE",
|
||||||
|
"BUHU",
|
||||||
|
"MILK",
|
||||||
|
"HABI",
|
||||||
|
"THUN",
|
||||||
|
"GARD",
|
||||||
|
"DON",
|
||||||
|
"YANGQ",
|
||||||
|
"SANAQ",
|
||||||
|
"BANQ",
|
||||||
|
"LUJ",
|
||||||
|
"PHIX",
|
||||||
|
"SIEI",
|
||||||
|
"EGG",
|
||||||
|
}
|
206
main.go
206
main.go
|
@ -1,30 +1,17 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/x509"
|
|
||||||
"encoding/pem"
|
|
||||||
"errors"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/rpc"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.xeserv.us/xena/route/routerpc"
|
"git.xeserv.us/xena/route/server"
|
||||||
r "github.com/GoRethink/gorethink"
|
|
||||||
"github.com/Xe/uuid"
|
|
||||||
"github.com/Yawning/bulb"
|
|
||||||
"github.com/facebookgo/flagenv"
|
"github.com/facebookgo/flagenv"
|
||||||
_ "github.com/joho/godotenv/autoload"
|
_ "github.com/joho/godotenv/autoload"
|
||||||
"github.com/koding/tunnel"
|
|
||||||
"github.com/sycamoreone/orc/tor"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -36,11 +23,7 @@ var (
|
||||||
torHashedPassword = flag.String("tor-hashed-password", "", "Tor hashed password")
|
torHashedPassword = flag.String("tor-hashed-password", "", "Tor hashed password")
|
||||||
torPassword = flag.String("tor-password", "hunter2", "Tor clear password")
|
torPassword = flag.String("tor-password", "hunter2", "Tor clear password")
|
||||||
webPort = flag.String("web-port", "9234", "HTTP ingress port for backends and users")
|
webPort = flag.String("web-port", "9234", "HTTP ingress port for backends and users")
|
||||||
)
|
domainSuffix = flag.String("domain-suffix", ".apps.xeserv.us", "Domain name suffix associated with the load balancer")
|
||||||
|
|
||||||
// RPC constants
|
|
||||||
const (
|
|
||||||
RPCPort uint16 = 39453
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -48,7 +31,7 @@ func main() {
|
||||||
flagenv.Parse()
|
flagenv.Parse()
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
|
|
||||||
s, err := create(&ServerConfig{
|
s, err := server.New(&server.ServerConfig{
|
||||||
ControlHost: *controlHost,
|
ControlHost: *controlHost,
|
||||||
ControlKeyFile: *controlKeyFile,
|
ControlKeyFile: *controlKeyFile,
|
||||||
RethinkDBHost: *rethinkDBHost,
|
RethinkDBHost: *rethinkDBHost,
|
||||||
|
@ -56,6 +39,8 @@ func main() {
|
||||||
TorDataDir: *torDataDir,
|
TorDataDir: *torDataDir,
|
||||||
TorHashedPassword: *torHashedPassword,
|
TorHashedPassword: *torHashedPassword,
|
||||||
TorPassword: *torPassword,
|
TorPassword: *torPassword,
|
||||||
|
WebPort: *webPort,
|
||||||
|
DomainSuffix: *domainSuffix,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -74,182 +59,3 @@ func main() {
|
||||||
|
|
||||||
hs.Serve(l)
|
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("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.OnionHostname = oi.OnionID + ".onion"
|
|
||||||
resp.Token = token
|
|
||||||
|
|
||||||
if req.Hostname != "" {
|
|
||||||
rs.Server.ts.AddHost(req.Hostname, token)
|
|
||||||
resp.Hostname = req.Hostname
|
|
||||||
}
|
|
||||||
rs.Server.ts.AddHost(resp.OnionHostname, token)
|
|
||||||
|
|
||||||
if oi.PrivateKey != nil {
|
|
||||||
resp.PrivKey = oi.PrivateKey
|
|
||||||
} else {
|
|
||||||
resp.PrivKey = req.PrivKey
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,263 @@
|
||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/x509"
|
||||||
|
"encoding/pem"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"net/rpc"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.xeserv.us/xena/route/database"
|
||||||
|
"git.xeserv.us/xena/route/lib/elfs"
|
||||||
|
"git.xeserv.us/xena/route/routerpc"
|
||||||
|
"github.com/Xe/uuid"
|
||||||
|
"github.com/Yawning/bulb"
|
||||||
|
"github.com/koding/tunnel"
|
||||||
|
"github.com/sycamoreone/orc/tor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RPC constants
|
||||||
|
const (
|
||||||
|
RPCPort uint16 = 39453
|
||||||
|
)
|
||||||
|
|
||||||
|
// Server is the main server type
|
||||||
|
type Server struct {
|
||||||
|
cfg *ServerConfig
|
||||||
|
|
||||||
|
db *database.DB
|
||||||
|
|
||||||
|
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
|
||||||
|
WebPort, DomainSuffix string
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new Server
|
||||||
|
func New(cfg *ServerConfig) (*Server, error) {
|
||||||
|
db, err := database.New(cfg.RethinkDBHost, 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("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,
|
||||||
|
|
||||||
|
db: db,
|
||||||
|
|
||||||
|
torCon: bc,
|
||||||
|
torCmd: tcmd,
|
||||||
|
torControlPath: torControlPath,
|
||||||
|
|
||||||
|
rpcS: rpcs,
|
||||||
|
rpcAddr: l.Addr().String(),
|
||||||
|
|
||||||
|
ts: ts,
|
||||||
|
}
|
||||||
|
|
||||||
|
rpcs.RegisterName("Urls", &RPCServer{Server: s})
|
||||||
|
go rpcs.Accept(l)
|
||||||
|
|
||||||
|
err = s.restore()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) restore() error {
|
||||||
|
rts, err := s.db.GetAllRoutes()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rt := range rts {
|
||||||
|
var block *pem.Block
|
||||||
|
|
||||||
|
block, _ = pem.Decode([]byte(rt.OnionKey))
|
||||||
|
pKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ports := []bulb.OnionPortSpec{
|
||||||
|
genPortSpec(80, "127.0.0.1:"+s.cfg.WebPort),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = s.torCon.AddOnion(ports, pKey, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
s.ts.AddHost(rt.Hostname, rt.Token)
|
||||||
|
s.ts.AddHost(rt.OnionHostname, rt.Token)
|
||||||
|
|
||||||
|
log.Printf("added: %s (%s)", rt.Hostname, rt.OnionHostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func genPortSpec(incoming uint16, outgoing string) bulb.OnionPortSpec {
|
||||||
|
return bulb.OnionPortSpec{
|
||||||
|
VirtPort: incoming,
|
||||||
|
Target: outgoing,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCServer is a Server wrapped to work inside the context of net/rpc
|
||||||
|
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:" + rs.cfg.WebPort,
|
||||||
|
},
|
||||||
|
}, req.PrivKey, false)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp.OnionHostname = oi.OnionID + ".onion"
|
||||||
|
resp.Token = token
|
||||||
|
|
||||||
|
if req.Hostname != "" {
|
||||||
|
rs.Server.ts.AddHost(req.Hostname, token)
|
||||||
|
resp.Hostname = req.Hostname
|
||||||
|
} else {
|
||||||
|
resp.Hostname = elfs.MakeName() + rs.cfg.DomainSuffix
|
||||||
|
rs.ts.AddHost(resp.Hostname, token)
|
||||||
|
}
|
||||||
|
rs.Server.ts.AddHost(resp.OnionHostname, token)
|
||||||
|
|
||||||
|
if oi.PrivateKey != nil {
|
||||||
|
resp.PrivKey = oi.PrivateKey
|
||||||
|
} else {
|
||||||
|
resp.PrivKey = req.PrivKey
|
||||||
|
}
|
||||||
|
|
||||||
|
err = rs.db.SaveRoute(resp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
Loading…
Reference in New Issue