only put password in file on first run

This commit is contained in:
AJ ONeal 2020-06-08 18:58:52 -06:00
parent befed81101
commit 05fdd8bb45
5 changed files with 174 additions and 75 deletions

View File

@ -12,6 +12,7 @@ import (
"net" "net"
"net/url" "net/url"
"os" "os"
"strconv"
"strings" "strings"
"time" "time"
@ -45,8 +46,6 @@ type Forward struct {
} }
func main() { func main() {
var err error
var provider challenge.Provider = nil
var domains []string var domains []string
var forwards []Forward var forwards []Forward
@ -64,6 +63,7 @@ func main() {
relay := flag.String("relay", "", "the domain (or ip address) at which the relay server is running") relay := flag.String("relay", "", "the domain (or ip address) at which the relay server is running")
secret := flag.String("secret", "", "the same secret used by telebit-relay (used for JWT authentication)") secret := flag.String("secret", "", "the same secret used by telebit-relay (used for JWT authentication)")
token := flag.String("token", "", "a pre-generated token to give the server (instead of generating one with --secret)") token := flag.String("token", "", "a pre-generated token to give the server (instead of generating one with --secret)")
bindAddrsStr := flag.String("listen", "", "list of bind addresses on which to listen, such as localhost:80, or :443")
locals := flag.String("locals", "", "a list of <from-domain>:<to-port>") locals := flag.String("locals", "", "a list of <from-domain>:<to-port>")
flag.Parse() flag.Parse()
@ -74,17 +74,18 @@ func main() {
} }
} }
if "" != *acmeDirectory { if len(*acmeDirectory) > 0 {
if *acmeStaging { if *acmeStaging {
fmt.Fprintf(os.Stderr, "pick either acme-directory or acme-staging\n") fmt.Fprintf(os.Stderr, "pick either acme-directory or acme-staging\n")
os.Exit(1) os.Exit(1)
return
} }
} }
if *acmeStaging { if *acmeStaging {
*acmeDirectory = certmagic.LetsEncryptStagingCA *acmeDirectory = certmagic.LetsEncryptStagingCA
} }
if "" == *locals { if 0 == len(*locals) {
*locals = os.Getenv("LOCALS") *locals = os.Getenv("LOCALS")
} }
for _, cfg := range strings.Fields(strings.ReplaceAll(*locals, ",", " ")) { for _, cfg := range strings.Fields(strings.ReplaceAll(*locals, ",", " ")) {
@ -109,77 +110,72 @@ func main() {
domains = append(domains, domain) domains = append(domains, domain)
} }
bindAddrs, err := parseBindAddrs(*bindAddrsStr)
if nil != err {
fmt.Fprintf(os.Stderr, "invalid bind address(es) given to --listen\n")
os.Exit(1)
return
}
if 0 == len(*secret) {
*secret = os.Getenv("SECRET")
}
ppid, err := machineid.ProtectedID(fmt.Sprintf("%s|%s", *appID, *secret)) ppid, err := machineid.ProtectedID(fmt.Sprintf("%s|%s", *appID, *secret))
if nil != err { if nil != err {
fmt.Fprintf(os.Stderr, "unauthorized device") fmt.Fprintf(os.Stderr, "unauthorized device\n")
os.Exit(1) os.Exit(1)
return
} }
ppidBytes, err := hex.DecodeString(ppid) ppidBytes, err := hex.DecodeString(ppid)
ppid = base64.RawURLEncoding.EncodeToString(ppidBytes) ppid = base64.RawURLEncoding.EncodeToString(ppidBytes)
if "" == *token { if 0 == len(*token) {
if "" == *secret {
*secret = os.Getenv("SECRET")
}
*token, err = authstore.HMACToken(ppid) *token, err = authstore.HMACToken(ppid)
if nil != err {
fmt.Fprintf(os.Stderr, "neither secret nor token provided\n")
os.Exit(1)
return
}
} }
if nil != err { if 0 == len(*relay) {
fmt.Fprintf(os.Stderr, "neither secret nor token provided")
os.Exit(1)
return
}
if "" == *relay {
*relay = os.Getenv("RELAY") // "wss://example.com:443" *relay = os.Getenv("RELAY") // "wss://example.com:443"
} }
if "" == *relay { if 0 == len(*relay) {
fmt.Fprintf(os.Stderr, "Missing relay url") fmt.Fprintf(os.Stderr, "Missing relay url\n")
os.Exit(1) os.Exit(1)
return return
} }
if "" == *acmeRelay { if 0 == len(*acmeRelay) {
*acmeRelay = strings.Replace(*relay, "ws", "http", 1) // "https://example.com:443" *acmeRelay = strings.Replace(*relay, "ws", "http", 1) // "https://example.com:443"
} }
if "" == *authURL {
*authURL = strings.Replace(*relay, "ws", "http", 1) // "https://example.com:443" if len(*relay) > 0 || len(*acmeRelay) > 0 {
if "" == *authURL {
*authURL = strings.Replace(*relay, "ws", "http", 1) // "https://example.com:443"
}
// TODO look at relay rather than authURL?
grants, err := telebit.Inspect(*authURL, *token)
if nil != err {
_, err := mgmt.Register(*authURL, *secret, ppid)
if nil != err {
fmt.Fprintf(os.Stderr, "failed to register client: %s\n", err)
os.Exit(1)
}
grants, err = telebit.Inspect(*authURL, *token)
if nil != err {
fmt.Fprintf(os.Stderr, "failed to authenticate after registering client: %s\n", err)
os.Exit(1)
}
}
fmt.Println("grants", grants)
} }
if "" != os.Getenv("GODADDY_API_KEY") { provider, err := getACMEProvider(acmeRelay, token)
id := os.Getenv("GODADDY_API_KEY")
secret := os.Getenv("GODADDY_API_SECRET")
if provider, err = newGoDaddyDNSProvider(id, secret); nil != err {
panic(err)
}
} else if "" != os.Getenv("DUCKDNS_TOKEN") {
if provider, err = newDuckDNSProvider(os.Getenv("DUCKDNS_TOKEN")); nil != err {
panic(err)
}
} else {
endpoint := *acmeRelay
if strings.HasSuffix(endpoint, "/") {
endpoint = endpoint[:len(endpoint)-1]
}
//endpoint += "/api/dns/"
if provider, err = newAPIDNSProvider(endpoint, *token); nil != err {
panic(err)
}
}
grants, err := telebit.Inspect(*authURL, *token)
if nil != err { if nil != err {
_, err := mgmt.Register(*authURL, *secret, ppid) fmt.Fprintf(os.Stderr, "%s\n", err)
if nil != err { os.Exit(1)
fmt.Fprintf(os.Stderr, "failed to register client: %s", err) return
os.Exit(1)
}
grants, err = telebit.Inspect(*authURL, *token)
if nil != err {
fmt.Fprintf(os.Stderr, "failed to authenticate after registering client: %s", err)
os.Exit(1)
}
} }
fmt.Println("grants", grants)
acme := &telebit.ACME{ acme := &telebit.ACME{
Email: *email, Email: *email,
StoragePath: *certpath, StoragePath: *certpath,
@ -190,6 +186,7 @@ func main() {
EnableTLSALPNChallenge: *enableTLSALPN01, EnableTLSALPNChallenge: *enableTLSALPN01,
} }
//mux := telebit.NewRouteMux(acme)
mux := telebit.NewRouteMux() mux := telebit.NewRouteMux()
mux.HandleTLS("*", acme, mux) mux.HandleTLS("*", acme, mux)
for _, fwd := range forwards { for _, fwd := range forwards {
@ -197,8 +194,30 @@ func main() {
//mux.ForwardTCP(fwd.pattern, "localhost:"+fwd.port, 120*time.Second) //mux.ForwardTCP(fwd.pattern, "localhost:"+fwd.port, 120*time.Second)
} }
connected := make(chan net.Conn) done := make(chan error)
for _, addr := range bindAddrs {
go func() {
fmt.Printf("Listening on %s\n", addr)
ln, err := net.Listen("tcp", addr)
if nil != err {
fmt.Fprintf(os.Stderr, "failed to bind to %q: %s", addr, err)
done <- err
return
}
if err := telebit.Serve(ln, mux); nil != err {
fmt.Fprintf(os.Stderr, "failed to bind to %q: %s", addr, err)
done <- err
return
}
}()
}
//connected := make(chan net.Conn)
go func() { go func() {
if "" == *relay {
return
}
timeoutCtx, cancel := context.WithDeadline(context.Background(), time.Now().Add(10*time.Second)) timeoutCtx, cancel := context.WithDeadline(context.Background(), time.Now().Add(10*time.Second))
defer cancel() defer cancel()
tun, err := telebit.DialWebsocketTunnel(timeoutCtx, *relay, *token) tun, err := telebit.DialWebsocketTunnel(timeoutCtx, *relay, *token)
@ -214,27 +233,91 @@ func main() {
err = mgmt.Ping(*authURL, *token) err = mgmt.Ping(*authURL, *token)
if nil != err { if nil != err {
fmt.Fprintf(os.Stderr, "failed to ping mgmt server: %s", err) fmt.Fprintf(os.Stderr, "failed to ping mgmt server: %s\n", err)
//os.Exit(1) //os.Exit(1)
} }
connected <- tun go func() {
}() for {
time.Sleep(10 * time.Minute)
go func() { err = mgmt.Ping(*authURL, *token)
for { if nil != err {
time.Sleep(10 * time.Minute) fmt.Fprintf(os.Stderr, "failed to ping mgmt server: %s\n", err)
err = mgmt.Ping(*authURL, *token) //os.Exit(1)
if nil != err { }
fmt.Fprintf(os.Stderr, "failed to ping mgmt server: %s", err)
//os.Exit(1)
} }
} }()
//connected <- tun
//tun := <-connected
fmt.Printf("Listening at %s\n", *relay)
err = telebit.ListenAndServe(tun, mux)
log.Fatal("Closed server: ", err)
done <- err
}() }()
tun := <-connected if err := <-done; nil != err {
fmt.Printf("Listening at %s\n", *relay) os.Exit(1)
log.Fatal("Closed server: ", telebit.ListenAndServe(tun, mux)) }
}
func parseBindAddrs(bindAddrsStr string) ([]string, error) {
bindAddrs := []string{}
for _, addr := range strings.Fields(strings.ReplaceAll(bindAddrsStr, ",", " ")) {
parts := strings.Split(addr, ":")
if len(parts) > 2 {
return nil, fmt.Errorf("too many colons (:) in bind address %s", addr)
}
if "" == addr || "" == parts[0] {
continue
}
var hostname, port string
if 2 == len(parts) {
hostname = parts[0]
port = parts[1]
} else {
port = parts[0]
}
if _, err := strconv.Atoi(port); nil != err {
return nil, fmt.Errorf("couldn't parse port of %q", addr)
}
bindAddrs = append(bindAddrs, hostname+":"+port)
}
return bindAddrs, nil
}
func getACMEProvider(acmeRelay, token *string) (challenge.Provider, error) {
var err error
var provider challenge.Provider = nil
if "" != os.Getenv("GODADDY_API_KEY") {
id := os.Getenv("GODADDY_API_KEY")
apiSecret := os.Getenv("GODADDY_API_SECRET")
if provider, err = newGoDaddyDNSProvider(id, apiSecret); nil != err {
return nil, err
}
} else if "" != os.Getenv("DUCKDNS_TOKEN") {
if provider, err = newDuckDNSProvider(os.Getenv("DUCKDNS_TOKEN")); nil != err {
return nil, err
}
} else {
if "" == *acmeRelay {
return nil, fmt.Errorf("No relay for ACME DNS-01 challenges given to --acme-relay")
}
endpoint := *acmeRelay
if strings.HasSuffix(endpoint, "/") {
endpoint = endpoint[:len(endpoint)-1]
}
//endpoint += "/api/dns/"
if provider, err = newAPIDNSProvider(endpoint, *token); nil != err {
return nil, err
}
}
return provider, nil
} }
type ACMEProvider struct { type ACMEProvider struct {

View File

@ -75,11 +75,10 @@ mv "$postgres_tmp/$postgres_dir" "$OPT_DIR/"
rm -f "$OPT_DIR/$postgres_lnk" rm -f "$OPT_DIR/$postgres_lnk"
ln -s "$OPT_DIR/$postgres_dir" "$OPT_DIR/$postgres_lnk" ln -s "$OPT_DIR/$postgres_dir" "$OPT_DIR/$postgres_lnk"
echo "postgres" > "${postgres_tmp}/pwfile"
mkdir -p "$POSTGRES_DATA_DIR" mkdir -p "$POSTGRES_DATA_DIR"
chmod 0700 "$POSTGRES_DATA_DIR" chmod 0700 "$POSTGRES_DATA_DIR"
if [ ! -f "$POSTGRES_DATA_DIR/postgresql.conf" ]; then if [ ! -f "$POSTGRES_DATA_DIR/postgresql.conf" ]; then
echo "postgres" > "${postgres_tmp}/pwfile"
"$OPT_DIR/$postgres_lnk/bin/initdb" \ "$OPT_DIR/$postgres_lnk/bin/initdb" \
-D "$POSTGRES_DATA_DIR/" \ -D "$POSTGRES_DATA_DIR/" \
--username postgres --pwfile "${postgres_tmp}/pwfile" \ --username postgres --pwfile "${postgres_tmp}/pwfile" \

View File

@ -97,6 +97,19 @@ func (c *ConnWrap) isTerminated() bool {
return true return true
} }
// how to know how many bytes to read? really needs timeout
b, err := c.Peek(2)
if len(b) >= 2 {
// TODO better detection?
// SSL v3.x / TLS v1.x
if 0x16 == b[0] && 0x03 == b[1] {
return false
}
}
if nil != err {
return true
}
switch conn := c.Conn.(type) { switch conn := c.Conn.(type) {
case *ConnWrap: case *ConnWrap:
return conn.isTerminated() return conn.isTerminated()

View File

@ -66,7 +66,7 @@ func ListenAndServe(tun net.Conn, mux Handler) error {
} }
// Serve Accept()s connections which have already been unwrapped and serves them with the given Handler // Serve Accept()s connections which have already been unwrapped and serves them with the given Handler
func Serve(listener *Listener, mux Handler) error { func Serve(listener net.Listener, mux Handler) error {
for { for {
client, err := listener.Accept() client, err := listener.Accept()
if nil != err { if nil != err {
@ -108,6 +108,10 @@ func (l *Listener) Close() error {
return nil return nil
} }
func (l *Listener) Addr() net.Addr {
return l.tun.LocalAddr()
}
// RouteBytes receives address information and a buffer and creates or re-uses a pipe that can be Accept()ed. // RouteBytes receives address information and a buffer and creates or re-uses a pipe that can be Accept()ed.
func (l *Listener) RouteBytes(srcAddr, dstAddr Addr, b []byte) { func (l *Listener) RouteBytes(srcAddr, dstAddr Addr, b []byte) {
// TODO use context to be able to cancel many at once? // TODO use context to be able to cancel many at once?

View File

@ -1 +1 @@
go run cmd/telebit/*.go --acme-agree=true --acme-relay http://devices.rootprojects.org:3010/api/dns --auth-url http://devices.rootprojects.org:3010/api --app-id test-id --secret k7nsLSwNKbOeBhDFpbhwGHv go run cmd/telebit/*.go --acme-agree=true --acme-relay http://devices.rootprojects.org:3010/api/dns --auth-url http://devices.rootprojects.org:3010/api --app-id test-id --secret k7nsLSwNKbOeBhDFpbhwGHv --listen 3443