diff --git a/boringproxy.go b/boringproxy.go index 2fe8446..0ac91cf 100644 --- a/boringproxy.go +++ b/boringproxy.go @@ -2,7 +2,6 @@ package boringproxy import ( "bufio" - "context" "crypto/tls" "encoding/json" "errors" @@ -21,7 +20,6 @@ import ( ) type Config struct { - WebUiDomain string `json:"webui_domain"` SshServerPort int `json:"ssh_server_port"` PublicIp string `json:"public_ip"` } @@ -153,9 +151,10 @@ func Listen() { if adminDomain == "" { - adminDomain = getAdminDomain(ip, certConfig) - - db.SetAdminDomain(adminDomain) + err = setAdminDomain(ip, certConfig, db) + if err != nil { + log.Fatal(err) + } } else { err = certConfig.ManageSync([]string{adminDomain}) if err != nil { @@ -167,17 +166,17 @@ func Listen() { users := db.GetUsers() if len(users) == 0 { db.AddUser("admin", true) - token, err := db.AddToken("admin") + //token, err := db.AddToken("admin") + _, err := db.AddToken("admin") if err != nil { log.Fatal("Failed to initialize admin user") } - log.Println("Admin token: " + token) - log.Println(fmt.Sprintf("Admin login link: https://%s/login?access_token=%s", adminDomain, token)) + //log.Println("Admin token: " + token) + //log.Println(fmt.Sprintf("Admin login link: https://%s/login?access_token=%s", adminDomain, token)) } config := &Config{ - WebUiDomain: adminDomain, SshServerPort: *sshServerPort, PublicIp: ip, } @@ -238,7 +237,7 @@ func Listen() { requestId := r.Form.Get("request-id") // Ensure the request exists - _, err := db.GetDNSRequest(requestId) + dnsRequest, err := db.GetDNSRequest(requestId) if err != nil { w.WriteHeader(500) io.WriteString(w, err.Error()) @@ -248,8 +247,23 @@ func Listen() { db.DeleteDNSRequest(requestId) domain := r.Form.Get("domain") - http.Redirect(w, r, fmt.Sprintf("https://%s/edit-tunnel?domain=%s", config.WebUiDomain, domain), 303) - } else if r.Host == config.WebUiDomain { + + if dnsRequest.IsAdminDomain { + db.SetAdminDomain(domain) + + // TODO: Might want to get all certs here, not just the admin domain + err := certConfig.ManageSync([]string{domain}) + if err != nil { + log.Fatal(err) + } + + http.Redirect(w, r, fmt.Sprintf("https://%s", domain), 303) + } else { + adminDomain := db.GetAdminDomain() + http.Redirect(w, r, fmt.Sprintf("https://%s/edit-tunnel?domain=%s", adminDomain, domain), 303) + } + + } else if r.Host == db.GetAdminDomain() { if strings.HasPrefix(r.URL.Path, "/api/") { http.StripPrefix("/api", api).ServeHTTP(w, r) } else { @@ -342,72 +356,66 @@ func (p *Server) passthroughRequest(conn net.Conn, tunnel Tunnel) { wg.Wait() } -func getAdminDomain(ip string, certConfig *certmagic.Config) string { +func setAdminDomain(ip string, certConfig *certmagic.Config, db *Database) error { action := prompt("\nNo admin domain set. Enter '1' to input manually, or '2' to configure through TakingNames.io\n") - - var adminDomain string - switch action { case "1": - adminDomain = prompt("\nEnter admin domain:\n") + adminDomain := prompt("\nEnter admin domain:\n") err := certConfig.ManageSync([]string{adminDomain}) if err != nil { log.Fatal(err) } + + db.SetAdminDomain(adminDomain) case "2": + log.Println("Get bootstrap domain") + + resp, err := http.Get("https://takingnames.io/dnsapi/bootstrap-domain") + if err != nil { + return err + } + defer resp.Body.Close() + body, err := io.ReadAll(resp.Body) + + bootstrapDomain := string(body) + + if resp.StatusCode != 200 { + fmt.Println(bootstrapDomain) + return errors.New("bootstrap domain request failed") + } + + log.Println("Get cert") + + err = certConfig.ManageSync([]string{bootstrapDomain}) + if err != nil { + log.Fatal(err) + } + requestId, _ := genRandomCode(32) - tnLink := fmt.Sprintf("https://takingnames.io/dnsapi?requester=%s&request-id=%s&request-type=%s", ip, requestId, "set-ip") - - // Create a temporary web server to handle the callback which contains the domain - - mux := http.NewServeMux() - - server := http.Server{ - Addr: ":80", - Handler: mux, + req := DNSRequest{ + IsAdminDomain: true, + Records: []*DNSRecord{ + &DNSRecord{ + Type: "A", + Value: ip, + TTL: 300, + }, + }, } - mux.HandleFunc("/dnsapi/callback", func(w http.ResponseWriter, r *http.Request) { - r.ParseForm() + db.SetDNSRequest(requestId, req) - domain := r.Form.Get("domain") - returnedReqId := r.Form.Get("request-id") - - if domain == "" { - log.Fatal("Blank domain from TakingNames.io") - } - - if returnedReqId != requestId { - log.Fatal("request-id doesn't match") - } - - adminDomain = domain - - err := certConfig.ManageSync([]string{adminDomain}) - if err != nil { - log.Fatal(err) - } - - go func() { - ctx := context.Background() - server.Shutdown(ctx) - }() - - http.Redirect(w, r, fmt.Sprintf("https://%s", adminDomain), 303) - }) - - fmt.Println("Use the link below to select a domain:\n\n" + tnLink) - - server.ListenAndServe() + tnLink := fmt.Sprintf("https://takingnames.io/dnsapi?requester=%s&request-id=%s", bootstrapDomain, requestId) + fmt.Println("Use the link below to select an admin domain:\n\n" + tnLink + "\n") default: log.Fatal("Invalid option") } - return adminDomain + return nil } func prompt(promptText string) string { diff --git a/database.go b/database.go index 51bfb76..70513cc 100644 --- a/database.go +++ b/database.go @@ -36,7 +36,8 @@ type DbClient struct { } type DNSRequest struct { - Records []*DNSRecord `json:"records"` + IsAdminDomain bool `json:"is_admin_domain"` + Records []*DNSRecord `json:"records"` } type DNSRecord struct { diff --git a/tunnel_manager.go b/tunnel_manager.go index 6a57285..6162497 100644 --- a/tunnel_manager.go +++ b/tunnel_manager.go @@ -79,7 +79,6 @@ func (m *TunnelManager) RequestCreateTunnel(tunReq Tunnel) (Tunnel, error) { } for _, tun := range m.db.GetTunnels() { - fmt.Println(tunReq.Domain, tun.Domain) if tunReq.Domain == tun.Domain { return Tunnel{}, errors.New("Tunnel domain already in use") } @@ -94,7 +93,7 @@ func (m *TunnelManager) RequestCreateTunnel(tunReq Tunnel) (Tunnel, error) { return Tunnel{}, err } - tunReq.ServerAddress = m.config.WebUiDomain + tunReq.ServerAddress = m.db.GetAdminDomain() tunReq.ServerPort = m.config.SshServerPort tunReq.ServerPublicKey = "" tunReq.Username = m.user.Username diff --git a/ui_handler.go b/ui_handler.go index 219ee04..7539f94 100644 --- a/ui_handler.go +++ b/ui_handler.go @@ -178,7 +178,9 @@ func (h *WebUiHandler) handleWebUiRequest(w http.ResponseWriter, r *http.Request h.db.SetDNSRequest(requestId, req) - tnLink := fmt.Sprintf("https://takingnames.io/dnsapi?requester=%s&request-id=%s", h.config.WebUiDomain, requestId) + adminDomain := h.db.GetAdminDomain() + + tnLink := fmt.Sprintf("https://takingnames.io/dnsapi?requester=%s&request-id=%s", adminDomain, requestId) templateData := struct { Domain string @@ -351,7 +353,8 @@ func (h *WebUiHandler) handleTokens(w http.ResponseWriter, r *http.Request, user qrCodes := make(map[string]template.URL) for token := range tokens { - loginUrl := fmt.Sprintf("https://%s/login?access_token=%s", h.config.WebUiDomain, token) + adminDomain := h.db.GetAdminDomain() + loginUrl := fmt.Sprintf("https://%s/login?access_token=%s", adminDomain, token) var png []byte png, err := qrcode.Encode(loginUrl, qrcode.Medium, 256)