only put password in file on first run
This commit is contained in:
parent
befed81101
commit
05fdd8bb45
|
@ -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 {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "neither secret nor token provided")
|
fmt.Fprintf(os.Stderr, "neither secret nor token provided\n")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if "" == *relay {
|
if 0 == len(*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 len(*relay) > 0 || len(*acmeRelay) > 0 {
|
||||||
if "" == *authURL {
|
if "" == *authURL {
|
||||||
*authURL = strings.Replace(*relay, "ws", "http", 1) // "https://example.com:443"
|
*authURL = strings.Replace(*relay, "ws", "http", 1) // "https://example.com:443"
|
||||||
}
|
}
|
||||||
|
// TODO look at relay rather than authURL?
|
||||||
if "" != os.Getenv("GODADDY_API_KEY") {
|
|
||||||
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)
|
grants, err := telebit.Inspect(*authURL, *token)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
_, err := mgmt.Register(*authURL, *secret, ppid)
|
_, err := mgmt.Register(*authURL, *secret, ppid)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "failed to register client: %s", err)
|
fmt.Fprintf(os.Stderr, "failed to register client: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
grants, err = telebit.Inspect(*authURL, *token)
|
grants, err = telebit.Inspect(*authURL, *token)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
fmt.Fprintf(os.Stderr, "failed to authenticate after registering client: %s", err)
|
fmt.Fprintf(os.Stderr, "failed to authenticate after registering client: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fmt.Println("grants", grants)
|
fmt.Println("grants", grants)
|
||||||
|
}
|
||||||
|
|
||||||
|
provider, err := getACMEProvider(acmeRelay, token)
|
||||||
|
if nil != err {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
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() {
|
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() {
|
||||||
|
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() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
time.Sleep(10 * time.Minute)
|
time.Sleep(10 * time.Minute)
|
||||||
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
|
||||||
tun := <-connected
|
//tun := <-connected
|
||||||
fmt.Printf("Listening at %s\n", *relay)
|
fmt.Printf("Listening at %s\n", *relay)
|
||||||
log.Fatal("Closed server: ", telebit.ListenAndServe(tun, mux))
|
err = telebit.ListenAndServe(tun, mux)
|
||||||
|
log.Fatal("Closed server: ", err)
|
||||||
|
done <- err
|
||||||
|
}()
|
||||||
|
|
||||||
|
if err := <-done; nil != err {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
|
|
@ -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" \
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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?
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue